Today lets see what is subclassing, categories and extensions in Objective C, and where, when and how to use these concepts.
Note: A complete working Xcode project copy is available for download, which includes all the required examples to understand these concepts practically at the end of this post.
1) Subclass in Objective C
Subclassing in simple words is changing the behavior of properties or methods of an existing class or in other words subclassing is inheriting a class and modifying the methods or properties of super class however you want.
Suppose for example consider a UITextField class, by default the placeholder text of UITextField will be of light gray color with default system font. If we want to change this style just subclass UITextField and override drawPlaceholderInRect method.
Example:
Create a class of type UITextField and name it some thing like CustomUITextFieldPlaceholderAppearance
CustomUITextFieldPlaceholderAppearance.h
#import <UIKit/UIKit.h>
@interface CustomUITextFieldPlaceholderAppearance : UITextField
@end
CustomUITextFieldPlaceholderAppearance.m
#import "CustomUITextFieldPlaceholderAppearance.h"
@implementation CustomUITextFieldPlaceholderAppearance
// override drawPlaceholderInRect method
- (void)drawPlaceholderInRect:(CGRect)rect {
// Set color and font size and style of placeholder text
[[UIColor redColor] setFill]; //set placeholder text color to red
[[self placeholder] drawInRect:rect withFont:[UIFont fontWithName:@"verdana" size:14.0]]; //set custom font style and size to placeholder text
}
@end
Now in your application wherever you want this custom look and feel for placeholder text of textfield you can just import this subclass header file (#import "CustomUITextFieldPlaceholderAppearance.h") and create an object of this class and you are done. In addition to this look and feel the default delegate methods and properties of UITextField will remain same.
2) Categories in Objective C
An Objective C category allows you add your own methods to an existing class.
Categories are also called as "informal protocols".
Suppose take an example, since Foundation Framework classes such as NSString, NSArray, NSDate etc… doesn’t have any access to modify, you can add your own methods in to these classes by the help of a category.
Consider NSString Class and if suppose we want to add a reverse string method to NSString class, so that in our application at any point of time any NSString object can call this category method and get a reversed string as a result. We can do this as below,
Note: Usually naming convention for category file is like OriginalClassName+CategoryName
Example:
Lets create a category class with a name something like NSString+NSString_ReverseString
NSString+NSString_ReverseString.h
#import <Foundation/Foundation.h>
@interface NSString (NSString_ReverseString)
- (NSString *)reverseString:(NSString *)yourString;
@end
NSString+NSString_ReverseString.m
#import "NSString+NSString_ReverseString.h"
@implementation NSString (NSString_ReverseString)
- (NSString *)reverseString:(NSString *)yourString
{
NSMutableString *reversedStr = [NSMutableString stringWithCapacity:[yourString length]];
[yourString enumerateSubstringsInRange:NSMakeRange(0,[yourString length])
options:(NSStringEnumerationReverse | NSStringEnumerationByComposedCharacterSequences)
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
[reversedStr appendString:substring];
}];
return reversedStr;
}
@end
Now in your application wherever you want to reverse a string then just import this category header file (#import "NSString+NSString_ReverseString.h"
) and call our reverseString: method from any of NSString object and it will reverse and return you the reversed string.
In the above example we have added a custom method called reverseString: to NSString class from the help of a category.
Note that in a category you can’t add an instance variable, since methods within a category are added to a class at runtime.
3) Extensions in Objective C
Extensions are similar to categories but the need of extension is different.
- Class extensions are often used to extend the public interface with additional private methods or properties for use within the implementation of the class.
- Extensions can only be added to a class for which you have the source code at compile time (the class is compiled at the same time as the class extension).
- Extensions will be local to a class file.
The syntax to declare class extension looks like,
@interface ClassName()
@end
since no name is given in the parentheses, class extensions are often referred to as anonymous categories.
Note Extensions can add instance variables.
Example:
@interface ABCExtension()
@property NSObject *yourProperty;
@end
the compiler will automatically synthesize the relevant accessor methods, as well as an instance variable, inside the primary class implementation.
If you add any methods in a class extension, these must be implemented in the primary implementation for the class.
Example:
In any of your class in implementation file(.m), say ViewController.m
@interface ViewController ()
-(void)printName:(NSString *)name;
@end
@implementation ViewController
-(void)printName:(NSString *)name
{
NSLog(@"%@",name);
}
In the above extension example printName: method is private to class ViewController, and cannot be accessed from outside the ViewController class.(even if you inherit since printName: is a private method their will not be any access to this method outside the class)
You can call this extension method only inside ViewController class, as below
[self printName:@"MyName"];
Usually people will use extensions to hide private information of a class without exposing them to access from any other class.
Finally few simple points to remember is
- Subclassing is better option if you want to customize an existing stuffs or functionalities, and
- Category is a best option if you want to add additional functionalities to an existing class