I have a sentence similar to the following: "NSString class and its mutable subclass, NSMutableString, it provides an extensive set of APIs for working,

I want to make every word begin with a lowercase letter and end with an uppercase letter. Tell me how best to implement it?

  • How did you try to solve this problem? - Ivan Kramarchuk
  • @IvanKramarchuk added the solution below, decided with the help of blocks, if you have any idea how else you can, it will be only a plus :) - Vlad Bataev

2 answers 2

To solve this problem, I recommend creating a category:

@interface NSString (AdditionalMethods) - (NSString* _Nonnull)withFirstCharLowercasedLastCharUppercased; - (NSString* _Nonnull)withFirstCharLowercasedLastCharUppercasedForEachWord; @end 

The withFirstCharLowercasedLastCharUppercased method makes the first lowercase letter, the last one - uppercase:

 - (NSString* _Nonnull)withFirstCharLowercasedLastCharUppercased { if (self.length == 0) { return self; } NSMutableString* result = [[NSMutableString alloc] initWithString:self]; [result replaceCharactersInRange:NSMakeRange(0, 1) withString:[self substringToIndex:1].lowercaseString]; [result replaceCharactersInRange:NSMakeRange(self.length - 1, 1) withString:[self substringFromIndex:self.length - 1].uppercaseString]; return result; } 

The withFirstCharLowercasedLastCharUppercasedForEachWord method calls withFirstCharLowercasedLastCharUppercased for each word, and then replaces it in the source line:

 - (NSString* _Nonnull)withFirstCharLowercasedLastCharUppercasedForEachWord { NSMutableString *result = [[NSMutableString alloc] initWithString:self]; [self enumerateSubstringsInRange:NSMakeRange(0, self.length) options:NSStringEnumerationByWords usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { [result replaceCharactersInRange:substringRange withString:substring.withFirstCharLowercasedLastCharUppercased]; }]; return result; } 

Example of use:

 NSString* text = @"The NSString class declares the programmatic interface for an object that manages immutable strings. An immutable string is a text string that is defined when it is created and subsequently cannot be changed."; NSLog(@"%@", text.withFirstCharLowercasedLastCharUppercasedForEachWord); // выводит "thE nSStrinG clasS declareS thE programmatiC interfacE foR aN objecT thaT manageS immutablE stringS. aN immutablE strinG iS A texT strinG thaT iS defineD wheN iT iS createD anD subsequentlY cannoT bE changeD." 
  • @Roman_Podymov your version will be better than my solution, thanks! - Vlad Bataev

Solved the problem using blocks, the solution will be described below.

 NSString* text = @"The NSString class declares the programmatic interface for an object that manages immutable strings. An immutable string is a text string that is defined when it is created and subsequently cannot be changed."; NSMutableString *lowerUpperString = [text mutableCopy]; [lowerUpperString enumerateSubstringsInRange:NSMakeRange(0,[lowerUpperString length]) options:(NSStringEnumerationByWords | NSStringEnumerationByComposedCharacterSequences) usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { NSMutableString* disfiguredString = [substring mutableCopy]; [disfiguredString replaceCharactersInRange:NSMakeRange(disfiguredString.length - 1, 1) withString:[[disfiguredString substringFromIndex:disfiguredString.length - 1] capitalizedString]]; [lowerUpperString replaceCharactersInRange:substringRange withString:disfiguredString]; *stop = enclosingRange.location + enclosingRange.length == lowerUpperString.length; }]; NSLog(@"%@", lowerUpperString); 

Got the following: ThE NSStrinG clasS declareS thE programmatiC interfacE foR aN objecT thaT manageS immutablE stringS. AN immutablE strinG iS a texT strinG thaT iS defineD wheN iT iS createD anDsittinglY cannoT bE changeD.

  • Shouldn't you end up with the string "thE nSStrinG clasS declareS ..."? - Roman Podymov
  • I expected this result, you need to play with the index - Vlad Bataev