Site Search
Homepage of Otaku No Zoku
Complete Archives of Otaku No Zoku
About Otaku No Zoku
Subscribe to Otaku No Zoku
Bookmark Otaku No Zoku

Objective-C Categories :

Objective-C supports inheritance (but not multiple inheritance) like any good object oriented language. However, like many newer OOP languages, such as C# and Ruby, Objective-C 2.0 also supports extension methods, which in Objective-C parlance are called Categories. If you are at all familiar with C# (3.0 and on) you might have created extension methods, extending the functionality of a pre-existing class, such as the String class, by defining new functions to handle compression or specific cases of localization.

Categories in Objective-C allow you to add new functions to an already existing class without deriving a whole new class from some arbitrary base class. You effectively extend an already existing class to acquire some new functionality without all the extra overhead.

Declaring a new category is almost identical to declaring the interface and implementation for a class. Declare the interface and implementation as normal, and in brackets, immediately after the class name in either the @interface or @implementation line of the class being extended, add the name of the category.

For example:

@interface NSString (ReallyCoolExtension)
… extension methods …
@end

Which would add your ReallyCoolExtension to the NSString class.

Overriding Existing Methods

By adding category extension methods to a class with the same name and signature of currently existing class methods you are also able to override the default behaviour of classes. Want to change upperCaseString to actually returned a CamelCaseString instead? You can do that. Of course, overriding established methods in classes is not always wise, especially if the base classes are part of the standard foundation library.

Only Methods Can Be Declared

Under normal circumstances categories only permit methods to be added to a class, not instance variables. It is possible to add new variables, after a fashion, to established classes, but that topic is beyond the scope of this short article.

Unique Category Names

When declaring a new category, the name of the category must be unique within the application. Two categories with conflicting names will cause unexpected application behaviour.

Naming Conventions

The example code below shows both the interface, the implementation, and the main() function to test the code all in a single file. Placing the @interface code in to a header .h file and the @implementation code in to the implementation .m file is of course the standard practice. The file naming convention for a category is to use the name of the class that the category extends, followed by a plus sign, +, followed by the name of the category. So in the example code below, the file names would be:

NSString+InverseCapitalisation.h
NSString+InverseCapitalisation.m

Adding A Category To A Class

The following example program adds a new category to the NSString class that converts the characters in the string to upper case. Once the category has been added to the NSString class, all NSStrings will be able to utilise the new functionality.

WARNING: The example code provided works on individual characters within the NSString object using plain C functions such as toupper() and isupper(). This code is not compatible with anything other than the most basic ASCII character set. The reason to use the standard C library for this example is to illustrate how Objective-C 2.0 Categories work, not to delve in to the esoteric subtleties of Unicode.

Steps

  1. Declare and implement the upper-case category to extend the NSString class.
    1. Define a Category extension method to perform an inverse capitalisation on a string.
    2. Iterate over the NSString object, changing lower-case letters to upper-case, and vice versa.
  2. Define the main function.
    1. Define a NSString containing mixed case text.
    2. Call the new category functionality to convert the text to inverse-case.
    3. Output the modified text string.

The Source Code

#import <Foundation/Foundation.h> 

@interface NSString (inverseCapitalisation) 

- (NSString *) inverseCapitalisationString; 

@end 

@implementation NSString (inverseCapitalisation) 

- (NSString *) inverseCapitalisationString 

{ 
    // This is a quick hack to convert upper case letters to lowercase, and vice versa 
    // It uses the standard C character manipulation functions so it will obviously not 
    // work on anything other than basic ASCII strings. 

    // get the length of the string that is to be manipulated
    int len = [self length]; 

    // create a string to hold our modified text
    NSMutableString *capitalisedString = [NSMutableString stringWithCapacity:len]; 

    // iterate over the original string, pulling out each character for inspection
    for (int i = 0; i < len; i++) 
    { 
        // get the next character in the original string
        char ch = [self characterAtIndex:i]; 

        // convert upper-case to lower-case, and lower-case to upper-case
        if (isupper(ch)) 
        { 
            ch = tolower(ch); 
        } 
        else if (islower(ch)) 
        { 
            ch = toupper(ch); 
        } 

        // append the manipulated character to the modified string
        [capitalisedString appendString:[NSString stringWithFormat:@"%c", ch]]; 
    } 

    // return the newly modified string
    return capitalisedString; 
} 
@end 

int main (int argc, const char * argv[]) 
{
    // standard Foundation housekeeping
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    // define a sample string to be inverse capitalised
    NSString *string = [NSString stringWithString:@"Hello World!"]; 

    // capitalise the string
    NSString *capital = [string inverseCapitalisationString]; 

    // output the original, unmodified string
    NSLog(@"String : %@", string); 

    // output the capitalised version of the string
    NSLog(@"Inverse Capitalised: %@", capital); 

    // standard Foundation housekeeping
    [pool drain]; 
    return 0; 
}

Program Output

2010-10-11 03:17:34.766 InverseSample[688:a0f] String : Hello World!
2010-10-11 03:17:34.780 InverseSample[688:a0f] Inverse Capitalised: hELLO wORLD!

Results

The results show that the original input string of “Hello World!” has been converted to “hELLO wORLD!” by inverting the case on each of the letters in the NSString. The inverseCapitlisationString function could have performed any number of operations on the NSString, and all future NSString objects declared within the application will have the functionality to perform this transformation very simply as though invoking any normal method on the NSString object.

Summary

Categories, A.K.A. extension methods are a great way to add functionality to an already existing class without having to completely derive a new class, which in many cases of where categories are useful, is not a desirable thing to do.

Be Sociable, Share!

Liked This Post?

Subscribe to the RSS feed or follow me on Twitter to stay up to date!