i'm steve

One Thing I Liked About Objective C Category

Sun 12 Jun 2012

Objective-C is becoming a popular language thanks to iPhone/iPad Development. It’s a language based on C with OO feature & Smalltalk-like messaging on top. It’s the primary language for developing Mac/iOS applications. Though being yet another programming language, there’s a feature I like most about Objective-C: Category.

Class Extension

Category offers a clean way to extend the functionality of an existing class, particularly classes which are closed source, e.g. Adding MD5 generation to NSString. An alternative to this is subclassing, which is often deemed tedious and unnecessary especially when we are only adding a tiny extra method. Here’s an example to show you:

// NSString+MD5.h
// Category
@interface NSString (MD5)
- (NSString*)getMD5String
@end

// NSString+MD5.m
@implementation NSString (MD5)
- (NSString*)getMD5String {
    NSLog("MD5 String")
    return MD5([self UTF8String]); // assume it's md5-ed
}
@end

// To use it:
#import "NSString+MD5.h"

- (void)TestitOut {
    NSString *text = @"Text To Be MD5-ed";
    NSString *md5edText = [text getMD5String];
}

As seen in the code, using Category is like “injecting” new method calls into an existing class. Using the additional function doesn’t require any declaration of new class/object but the original object from the class itself, which is clean n neat. Note also, any subclass of the “injected” class would contain also that new method, as long as the header file which contains the Category is imported.

Private Instance Variable

With the current LLVM compiler, Category could also serve as a way to hide instance variables & methods from exposing in the public interface. Simply create an Category with empty CategoryName, and declare in it any private/hidden variable/methods you wish to have in the class.

// MyClass.h
@interface MyClass : NSObject
@property (strong, nonatomic)NSString *value; // public variable
- (void)publicMethod; // public method
@end

// MyClass.m
@interface MyClass ()
@property (strong, nonatomic)NSString *hiddenValue; // private variable
- (void)privateMethod; // private method
@end

@implementation MyClass
@synthesize value;
@synthesize hiddenValue;

- (void)publicMethod {
    NSLog(@"Public Method");
}
- (void)privateMethod {
    NSLog(@"Private Method");
}

@end

This way, “private variable” and “private method” would not be available to any classes other than itself, and it’s particularly useful when certain aspect of a class is to be hidden from external/outside region.

Do put Category into great use

Using Category properly, could give you the power of extensibility and flexibility. Not only is it elegant & simple to implement, it also helps reduce the amount of tedious code.

*Don’t abuse something just because you learnt about it - “Subclassing” is still preferred in some occasion.