Tel Tel - 4 months ago 14x
Swift Question

It's possible to convert a string to uppercase excluding certain words in Swift?

I would like to convert a string to Title case but excluding some words that don't need to be changed, as names of products, services and other trademark names.

With this code:

var storyTtitle = "Presented the new PowerBook"
let newStr = str.capitalizedStringWithLocale(NSLocale.currentLocale())

The result here is: "Presented The New Powerbook", unfortunately changing the word "Powerbook", in this case, it's a mistake. Does anyone know if there is a way to exclude some words, maybe contained in a list?


You can use enumerateSubstringsInRange() with the .ByWords options to enumerate all words in a string. This has the advantage that it works correctly even if a word is not delimited by space characters.

Your idea from above comment

the words that already contain a capital letter (eg iPhone, OS X, Xcode, MacBook, iOS) are not changed, while all words that do not contain any capital letter are subject to possible change

can then be implemented like this:

let storyTtitle = "Presented 'the' new PowerBook!  (or iPhone?)"

var newTitle = storyTtitle
var offset = 0
storyTtitle.enumerateSubstringsInRange(storyTtitle.characters.indices, options: .ByWords) {
    (substring, substringRange, _, _) in
    if let oldString = substring where oldString == oldString.lowercaseString {
        let range = substringRange.startIndex.advancedBy(offset) ..< substringRange.endIndex.advancedBy(offset)
        let newString = oldString.capitalizedString
        newTitle.replaceRange(range, with: newString)
        offset += newString.characters.count - oldString.characters.count

// Presented 'The' New PowerBook!  (Or iPhone?)

The offset variable and the "complicated" range calculations are necessary because the uppercase version of a string does not necessarily have the same number of characters as the lowercase version. For example, in German, the uppercase string for "ß" is "SS".