Search code examples
swiftnsstring

How to capitalize first word in every sentence with Swift


By taking into account of user locale, how can I capitalize the first word of each sentence in a paragraph? What I want to achieve is no matter the case inside the sentence, the first letter of each word will be uppercase and the rest will be lowercase. I can do only one sentence by first converting everything to lower case, then get first letter and make uppercase and finally add them up together. My question is different than How to capitalize each word in a string using Swift iOS since I don't want to capitalize each word. I just want to capitalize the first word of each sentence. capitalizedString turns

"this is first sentence. this is second sentence."

to

"This Is First Sentence. This Is Second Sentence."

What I want is

"This is first sentence. This is second sentence."

My question is also different than Capitalise first letter of every sentence Since @rintaro's code doesn't work on my below example. It keeps capital letters in original text intact. With @rintaro's code;

before

"someSentenceWith UTF text İŞğĞ. anotherSentenceğüÜğ"

after

"SomeSentenceWith UTF text İŞğĞ. AnotherSentenceğüÜğ."

What I want to achieve,

"Somesentencewith utf text işğğ. Anothersentenceğüüğ." 

My code below can only do partial conversion.

var description = "someSentenceWith UTF text İŞğĞ. anotherSentenceğüÜğ"
description = description.lowercaseStringWithLocale(NSLocale.currentLocale())
let first = description.startIndex
let rest = advance(first,1)..<description.endIndex
let capitalised = description[first...first].uppercaseStringWithLocale(NSLocale.currentLocale()) + description[rest]

I will really appreciate if you can please read my question carefully, since this is the third time I am editing the question. I am really sorry if I couldn't ask it clearly since I am not a native speaker. So even though @rintaro answered similar question, his answer doesn't solve my problem. @martin-r suggests a Objective-C answer which again doesn't solve the problem I have. There were another user eric something who also suggested another answer but deleted afterwards. I just can't understand why several people suggest different answer which doesn't answer my question.


Solution

  • You can use Regular Expressions to achieve this. I'm adding this function as a String extension so it will be trivial to call in the future:

    extension String {
    
        func toUppercaseAtSentenceBoundary() -> String {
            var string = self.lowercaseString
    
            var capacity = string.utf16Count
            var mutable = NSMutableString(capacity: capacity)
            mutable.appendString(string)
    
            var error: NSError?
    
            if let regex = NSRegularExpression(
                pattern: "(?:^|\\b\\.[ ]*)(\\p{Ll})",
                options: NSRegularExpressionOptions.AnchorsMatchLines,
                error: &error
                ) {
    
                if let results = regex.matchesInString(
                    string,
                    options: NSMatchingOptions.allZeros,
                    range: NSMakeRange(0, capacity)
                    ) as? [NSTextCheckingResult] {
    
                        for result in results {
                            let numRanges = result.numberOfRanges
                            if numRanges >= 1 {
                                for i in 1..<numRanges {
                                    let range = result.rangeAtIndex(i)
                                    let substring = mutable.substringWithRange(range)
                                    mutable.replaceCharactersInRange(range, withString: substring.uppercaseString)
                                }
                            }
                        }
                }
            }
    
            return mutable
        }
    }
    
    var string = "someSentenceWith UTF text İŞğĞ. anotherSentenceğüÜğ.".toUppercaseAtSentenceBoundary()