Tag Archives: objective c extension

Objective-C – Categories

Every developer, good or bad, at least those who have followed the programming courses at any university remembers some design patterns, MVC, Singleton and some of the also say Decorator.

In the iOS framework, Apple has used, and has guided the developers to use certain patterns, if we talk about the general architecture we most of the times find Model View Controller, if we want to use the notification system, we find out they used Observer pattern, and the list could go on.

Objective-C  is a hybrid language, which took, various parts for other languages, and evolved a lot in its over 32 years of existence. It has many great features, which helps you get your work done (eq. blocks), but it also has its lacks, you can NOT set the visibility of a a method as being private or protected because of the dynamism of the language.

Categories

In the beginning of this post, I’ve mentioned the Decorator pattern, and that is because this post should be about categories, Objective-C categories, and those two are somehow related.

With the Decorator pattern, you would add some new functionality to an existing class, that is the main purpose of Objective-C categories but with some constraints.

If you have started working in iOS you probably did already use categories, without knowing they are called like that, but enough talk lets jump to examples.

@interface HelloWorldObjC : NSObject

@property (strong, nonatomic) NSString *greeting;

- (void)saySomething;

@end

We declared an interface for a class which has one method, and one property, a greeting which is a string which will be printed by the say something method.

@interface HelloWorldObjC()

@property NSString *beforeGreetingString;

@end

@implementation HelloWorldObjC

#pragma mark - Lifecycle

- (id)init {

self = [super init];

if (self) {

self.beforeGreetingString = [NSStringstringWithFormat:@"%p", self];

self.greeting = @"Hello there!";

}

returnself;

}

#pragma mark - Public methods

- (void)saySomething {

NSLog(@"%@ says: %@", self.beforeGreetingString, self.greeting);

}

@end

As for the .m file, the implementation, as you can see there is another place where you could declare variables, making them “private”, that section @interface ClassName() is a special type of category called extensions. That is why I said in the beginning of this post that you might have used categories without knowing how they are called if you are new to ObjC. You can define an extension in the .m file of a certain class, where the @implementation of that class resides and create new properties which your class will be able to use. One thing to mention about this properties is the fact that they are synthesised, which means you get a getter, a setter and a backing ivar for your property. Moreover, you can also declare methods in the extension. Long story short, everything you declare here, can only be used in the @implementation section, if another class inherits or someone makes a category over this class, you will not be able to access anything defined inside the extension, and you will only have access to the things defined in the .h (@interface) file (without using some tricks at least.).

The initializer sets the greeting to a default one, in case someone forgets to set it when using the object and also sets the value of the interface defined property to the memory address of the current object.

The saySomething method only displays a string composed of the value of the address of the object in memory, and the defined greeting.

A real category

This is supposed to be about categories, but where are them? Ok lets see what a proper category looks like.

@interface HelloWorldObjC(Smile)

- (void)addSmileToGreeting;

@end

In another file usually named “HelloWorldObjC+Smile.h” we can add a new category, as you can see, the declaration is pretty straight forward, you declare it like any other class, without the inheritance and with a unique name in between parenthesis. What can we declare here? Well there are a few rules, you can define new methods and even properties, the compiler won’t complain if you provide the getters and setters in the implementation section your program won’t even crash. Basically what you can do here is add some new methods, some new functionalities to your original class, but you can not alloc new memory for it, that is why you can not add new properties backed by an ivar, because the categories are not new objects, they are the same object as the original class. To make it easier for you to understand, you can do an  category for every class you want (YES event for classes from Foundation, UIKit and so on), and you can use the methods you add to those classes using a category wherever you implement the header with the definition of the category. Now picture the following scenario, you are working with NSStrings all over the app, I come along and make a category over NSString and add new properties to it, what is suppose the system to do? Add those variables to all the objects, of NSStrings, wherever I import my header? The answer is NO, categories are not allowed to modify the size of the object in memory by adding some new values to it. That being said, you can not add properties, and ivars to a category. Another restriction is the fact that you can not overwrite methods on the base class, for obvious reasons.

@implementation HelloWorldObjC(WithSmile)

- (void)addSmileToGreeting {

[self.greeting stringByAppendingString:[NSStringstringWithFormat:@"%C", 0xe04f]];

}

@end

As for the implementation of the category in the “HelloWorldObjC+Smile.m” file, we only add an emoji to the current greeting message.

Well this doesn’t look like much, what can I use them for? Well there are many usages, for example you can use them to explicitly mark for the people in your team which methods are “private” or any other sort of example where you use a category in order to make your code more readable. But by far the most common usage is by adding some sort of functionality to a certain class, in my projects i usually make a category over UIColor so that i can initialize a colour from a hex string, you can put there all sorts of helpers on any class for the app you’re building.