As an alternative to subclassing, Objective-C categories provide a means to add methods to a class. What’s intriguing, is that any methods that you add through a category become part of the class definition, so to speak. In other words, if you add a method to the NSString class, any instance, or subclass, of NSString will have access to that method.
Defining a category is identical to defining the interface for a class, with one small exception: you add a category name inside a set of parenthesis after the interface declaration. The format is shown below:
@interface ClassToAddMethodsTo (category)
...methods go here
For example, below I’ve defined a category that adds a method to the NSString class. The method reverseString adds the capability to all NSString objects to reverse the characters in the string.
@interface NSString (reverse)
-(NSString *) reverseString;
As with the @interface declaration, the @implementation section changes only in that the category name is added to the definition. Below is the implementation of the interface defined above. Notice how in both cases I added (reverse) , which is the category name I assigned.
@implementation NSString (reverse)
-(NSString *) reverseString
int len = [self length];
// Auto released string
reversedStr = [NSMutableString stringWithCapacity:len];
// Probably woefully inefficient...
while (len > 0)
[NSString stringWithFormat:@"%C", [self characterAtIndex:--len]]];
What follows is a short example to showing how one might use the above category.
int main (int argc, const char * argv)
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *str = [NSString stringWithString:@"Fubar"];
NSLog(@"String: %@", str);
rev = [str reverseString];
The output of the above example is shown here:
Categories can also be used to override methods the class inherits, again, providing an alternative to subclassing. You can always access the overridden method using super . I would assume from an internal (compiler/code generation) perspective, this could lead to less code/overhead as compared to creating a subclass solely to override a method (caveat: I have no proof that is true).
Dividing Source Code into Separate File
Although I haven’t given this a go, categories provide an interesting opportunity to disperse the implementation of a class across one or more files. The Objective-C Programming Guide lists several benefits of this including:
- Opportunity to group together methods that perform similar tasks.
- Configuring classes differently for various applications, yet maintaining one set of code.
The recommended naming convention for a category is “ClassToAddMethodsTo+CatgoryName” for instance, I used the following filenames for the interface and implementation of the above category code:
You cannot add instance variables to a class through a category. Also, category names must be unique across an application.
I’ve attached the Xcode project for the above example if you’d like to give it a try.
In the next post I’ll show another example of using categories – the example will show one approach for hiding methods within in a class, as Objective-C does not offer support for private methods.