11th
Polishing Objective-C: Pulling Up into Categories
Objective-C with Cocoa does a lot for you, but if you are used to other languages and frameworks, you’ll quickly pine for the convenience methods that are missing. Lets say that you need to trim whitespace from strings. In Java, you can trim the whitespace from a String object like this:
String trimmedString = myString.trim();
No simple trim method exists in the Objective-C NSString class, so I’ll use Google to find a code snippet to do the same thing. Soon the snippet is sprinkled throughout my code:
NSString *trimmedString = [myString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]
The result is very repetitive and verbose. If I want use this snippet in multiple places, I should extract it into a method:
-(NSString*)trimString:(NSString*)string
{
return [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
This reduces each trim operation to:
NSString *trimmedString = [self trimString:myString];
If I want to use it in multiple classes I can go further by pulling it out and making it a class method inside of a Utility class so it is accessible to all of my classes:
+(NSString*)trimString:(NSString*)string //...
NSString* trimmedString = [Utils trimString:myString];
Categories
The method is pretty clean, but wouldn’t you rather call a trim method directly on a string object? Perhaps the most powerful refactoring tool in Objective-C is the category. With categories, we can pull methods up into a class that is already defined by a framework. In this case, we’ll also define trim as a read only property for conciseness.
Create a header file.
//NSString+Trim.h @interface NSString(MyCategories) @property(nonatomic, readonly) NSString *trim; // or stringByTrimming, if you want to name like Apple for derived objects. @end
Create an implementation file.
//NSString+Trim.m
@implementation NSString(MyCategories)
(NSString*)trim
{
return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
@end
Include the category in your prefix headers file(myApp.pch).
//myApp.pch #include "NSString+Trim.h"
Result
The result is far more concise and readable than the original code:
NSString *trimmedString = myString.trim;
To see many more examples of convenience methods pulled up into categories, see the es_ios_utils library.