Objective-C: Categories

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:

Overriding Methods

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.

Naming Conventions

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:

  • NSString+Reverse.h
  • NSString+Reverse.m

Caveats

You cannot add instance variables to a class through a category. Also, category names must be unique across an application.

Source Code

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.

Leave a Reply

Your email address will not be published. Required fields are marked *