How to use Categories in Objective-C

Objective-C has a feature called Categories. These are used to extend existing classes. The principle is different than subclassing in that a Category will behave like the original class with additions, rather than a completely different class.

For example, if we’d subclass NSString then the resulting class name would be something like YourStringClass. We would hence need to instantiate it with [[YourStringClass alloc]init]. By contrast, a Category is instantiated and used like the original class (such as [[NSString alloc]init], however additional methods we provide are henceforth included.

We need separate header and implementation files for our Category, just like for a regular class. Apple recommend to name such files by starting with the superclass, followed by a plus sign, followed by your Category name.

In this example we’ll create a Category for NSString called Test. Hence we need NSString+Test.h and .m files. Xcode 6 no longer provides a mechanism for that, so either empty .h and .m files will suffice, or alternatively create a standard subclass and overwrite the relevant sections.

Here’s NSString+Test.h:

@import Foundation;

@interface NSString (Test)

- (NSString *)myModification;

@end

Instead of separating our class name from the superclass with a semicolon, we’ll use brackets. We add one public method here. We’ll write the code for it in NSString+Test.m:

#import "NSString+Test.h"

@implementation NSString (Test)

- (NSString *)myModification {
    
    // add your code here
    return @"Result!";
}

@end

No big surprises here either: we simply import the header file and write our method – a simple one will do here, returning “Result!”. Notice the way we declare the @implementation, again with brackets.

Here’s how we call the extended class from somewhere else, for example a view controller:

#import "ViewController.h"
#import "NSString+Test.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {

    [super viewDidLoad];
    
    // call my own method
    NSString *result = [[NSString alloc]init];
    NSLog(@"%@", [result myModification]);
}

@end

After importing the Category we can instantiate an NSString object and use our own method as if Apple had baked it right into the Foundation Framework. How cool is that?

Singletons

Categories appear to be even cooler when we implement a singleton. That’s a method we can call on the class without having to instantiate it first. While the above example makes little difference beside convenience, when we call something like [[NSString myKillerExtension] it really feels as if our code is part of the Foundation Framework.

Defining a singleton works just like defining a standard method, but instead of the minus sign we use a plus sign. I’m also demonstrating how to take a parameter in our method:

// singleton signature in header file
+(NSString *)specialInstruction:(NSString *)parameter;

// and in the implementation file
+(NSString *)specialInstruction:(NSString *)parameter {
    
    // singleton implementaion
    NSString *result = [NSString stringWithFormat:@"The parameter was %@.", parameter];
    return result;
}

We can now call the singleton as it it was part of the NSString class:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // call my singleton
    result = [NSString specialInstruction:@"testing"];
    NSLog(@"%@", result);
}

Now go forth and categorise!





Leave a Reply