How to capitalize the first word of the sentence in Objective-C?

24,602

Solution 1

Here is another go at it:

NSString *txt = @"hi my friends!";
txt = [txt stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[txt substringToIndex:1] uppercaseString]];

For Swift language:

txt.replaceRange(txt.startIndex...txt.startIndex, with: String(txt[txt.startIndex]).capitalizedString)

Solution 2

The accepted answer is wrong. First, it is not correct to treat the units of NSString as "characters" in the sense that a user expects. There are surrogate pairs. There are combining sequences. Splitting those will produce incorrect results. Second, it is not necessarily the case that uppercasing the first character produces the same result as capitalizing a word containing that character. Languages can be context-sensitive.

The correct way to do this is to get the frameworks to identify words (and possibly sentences) in the locale-appropriate manner. And also to capitalize in the locale-appropriate manner.

[aMutableString enumerateSubstringsInRange:NSMakeRange(0, [aMutableString length])
                                   options:NSStringEnumerationByWords | NSStringEnumerationLocalized
                                usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
    [aMutableString replaceCharactersInRange:substringRange
                                  withString:[substring capitalizedStringWithLocale:[NSLocale currentLocale]]];
    *stop = YES;
}];

It's possible that the first word of a string is not the same as the first word of the first sentence of a string. To identify the first (or each) sentence of the string and then capitalize the first word of that (or those), then surround the above in an outer invocation of -enumerateSubstringsInRange:options:usingBlock: using NSStringEnumerationBySentences | NSStringEnumerationLocalized. In the inner invocation, pass the substringRange provided by the outer invocation as the range argument.

Solution 3

Use

- (NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator

and capitalize the first object in the array and then use

- (NSString *)componentsJoinedByString:(NSString *)separator

to join them back

Solution 4

pString = [pString
           stringByReplacingCharactersInRange:NSMakeRange(0,1)
           withString:[[pString substringToIndex:1] capitalizedString]];

Solution 5

An alternative solution in Swift:

var str = "hello"

if count(str) > 0 {
    str.splice(String(str.removeAtIndex(str.startIndex)).uppercaseString, atIndex: str.startIndex)
}
Share:
24,602
wal
Author by

wal

Updated on September 09, 2020

Comments

  • wal
    wal over 3 years

    I've already found how to capitalize all words of the sentence, but not the first word only.

    NSString *txt =@"hi my friends!"
    [txt capitalizedString];
    

    I don't want to change to lower case and capitalize the first char. I'd like to capitalize the first word only without change the others.

  • Teja Kantamneni
    Teja Kantamneni about 14 years
    I am pretty alien to Objective-c, but you have to do so much to just capitalize the word??
  • Tuomas Pelkonen
    Tuomas Pelkonen about 14 years
    Yes, to capitalize the first word only. Unfortunately, Objective-C is not like Python where every operation can be done on one line.
  • Chuck
    Chuck about 14 years
    @Teja: NSString does not natively support doing something to just one "word" in a string, and it's quite a verbose language anyway, so yes.
  • Johan Kool
    Johan Kool about 14 years
    Just make sure that the string is always at least 1 character long, or that you are ready to handle the exception thrown when that's not the case.
  • looneydoodle
    looneydoodle almost 12 years
    Add a if([txt length] > 1) check before you replace the string with the capitalized string.
  • Johan Kool
    Johan Kool almost 12 years
    @looneydoodle You mean if ([txt length] > 0). It works fine if the length is 1.
  • John Erck
    John Erck over 10 years
    Suggested edit: Add semi-colon as last character of first line. Would avert Xcode error on copy paste.
  • Ken Thomases
    Ken Thomases almost 10 years
    This answer is wrong. See my answer for the correct approach.
  • Authman Apatira
    Authman Apatira about 9 years
    For those who'd like to capitalize the first letter of every word, just change the last line to read *stop = enclosingRange.location + enclosingRange.length == self.length;
  • Ken Thomases
    Ken Thomases about 9 years
    If you want to capitalize every word, then there's no need to enumerate by words at all. That's the default behavior of -capitalizedStringWithLocale:. Even if you did want to enumerate every word, the way to do that is to simply never set *stop. The enumeration will naturally end at the end of the string. (In general in Cocoa's enumeration-with-block methods, you should never set *stop unless you're setting it to true. That's mostly important in concurrent enumerations, but it's in the design contract for all cases.)
  • Johan Kool
    Johan Kool almost 9 years
    See my other answer for a Swift solution to the problem of capitalizing the first character in a string. Ken Thomases has a point that you need to take localisation in account, and I recommend his answer is that is what you need, but in many cases this approach is sufficient.
  • keithbhunter
    keithbhunter over 7 years
    For languages where every noun is capitalized, like German, this will not work. It will only capitalize the first word in the sentence instead of every noun.
  • Ken Thomases
    Ken Thomases over 7 years
    @keithbhunter, OK, but that's not what the question was about. And I'd be surprised if there were any API which did the right thing for the situation you posit.
  • Arpit B Parekh
    Arpit B Parekh about 4 years
    What is splice ?
  • Johan Kool
    Johan Kool about 4 years
    @ArpitBParekh This code is old. It worked in Swift at the time I posted it, but splice as been replaced since.
  • Arpit B Parekh
    Arpit B Parekh about 4 years
    Thnak you for the answer @Johan Kool