As an alternative to subclassing, Objective-C categories provide a means to add methods to a class. Whats 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 @end
For example, below Ive 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; @end
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 NSMutableString *reversedStr; int len = self length; // Auto released string reversedStr = NSMutableString stringWithCapacity:len; // Probably woefully inefficient... while len > 0 reversedStr appendString: NSString stringWithFormat:@"%C", self characterAtIndex:--len; return reversedStr; @end
What follows is a short example to showing how one might use the above category.
#import <Foundation/Foundation.h> #import "NSString+Reverse.h" int main int argc, const char * argv NSAutoreleasePool *pool = NSAutoreleasePool alloc init; NSString *str = NSString stringWithString:@"Fubar"; NSString *rev; NSLog@"String: %@", str; rev = str reverseString; NSLog@"Reversed: %@",rev; pool drain; return 0;
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 havent 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.
Ive attached the Xcode project for the above example if youd like to give it a try.
In the next post Ill 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.