Anonymous users keep asking:
How do I remove whitespace characters from a string?
A quick way to do that is to first split the words in the string by whitespace characters and then join them back together without seperator. But there is a more elegant way to achieve this, that’s reusable at the same time: extend NSString by adding a category to compress whitespace to an arbitrary seperator.
If you really don’t want any spaces in your NSString then that’s one way to do it:
NSString *stringWithSpaces = @" A String \t With Spaces "; NSArray *comps = [stringWithSpaces componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; NSString *stringRejoined = [comps componentsJoinedByString:@""]; NSLog(stringRejoined); |
This uses the built-in Character Set comprised of all that is whitespace, even tabulators, to split the string. If you join the parts together with @” ” instead of an empty string you find that multiple whitespace character also cause multiple empty strings to be added to the comps array. Note that the whitespaceCharacterSet does not include newline characters, for those you would have to use whitespaceAndNewlineCharacterSet instead.
If you want to compress the whitespaces to single space characters you have to add an additional step. You need to make a copy of the components only keeping the non-empty ones.
NSString *stringWithSpaces = @" A String \t With Spaces "; NSArray *comps = [stringWithSpaces componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; NSMutableArray *nonemptyComps = [[[NSMutableArray alloc] init] autorelease]; // only copy non-empty entries for (NSString *oneComp in comps) { if (![oneComp isEqualToString:@""]) { [nonemptyComps addObject:oneComp]; } } NSString *stringRejoined = [nonemptyComps componentsJoinedByString:@" "]; NSLog(stringRejoined); |
A utility function like this would be really nice to have as a standard in NSString, don’t you think?
Well, here’s today’s bonus for you! I am showing you how all your NSStrings can get the ability to have their whitespace compressed:
NSString+Whitespace.h
#import @interface NSString (Whitespace) // Note: a category implementation does not have ivars in { } - (NSString *)stringByCompressingWhitespaceTo:(NSString *)seperator; @end |
NSString+Whitespace.m
#import "NSString+whitespace.h" @implementation NSString (Whitespace) - (NSString *)stringByCompressingWhitespaceTo:(NSString *)seperator { NSArray *comps = [self componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; NSMutableArray *nonemptyComps = [[[NSMutableArray alloc] init] autorelease]; // only copy non-empty entries for (NSString *oneComp in comps) { if (![oneComp isEqualToString:@""]) { [nonemptyComps addObject:oneComp]; } } return [nonemptyComps componentsJoinedByString:seperator]; // already marked as autoreleased } @end |
One great feature of objective-C is that you can extend existing classes by just creating a new so-called category. This way you don’t have to subclass standard classes like NSString but are free to teach those all the tricks that you can think of. A new category is added to a class as shown above, note that you don’t specify a new class name but just NSString, no colon to signify inheritance and in brackets the name of the new category.
With these two files added to your project you can now simply import the header and use it comfortably:
#import "NSString+Whitespace.h" NSString *stringWithSpaces = @" A String \t With Spaces "; NSString *resultString = [stringWithSpaces stringByCompressingWhitespaceTo:@"_"]; NSLog(resultString); |
Now you see why creating utility functions in objective-C is best done by creating a new category for the default class type you are working on. Now you know how categories look like and I am looking forward to seeing you creating your own extensions.
Categories: Q&A
Thank you! Your tip was really helpful. Not quite what I needed, but it pushed me in the right direction.
Compressing all whitespace to simple spaces really should be a default. It is weird that Apple does not have this. Even they could have needed it!
Just look at all that whitespace included in the .webhistory files under the Full Page Text key! Makes out several megabytes of just wasted on whitespace, if you have a large web cache/history.
You’re welcome! Did you manage to achieve what you needed?
This is great! thank you so much. Keep up the #AwesomeCode!