Categories for Extending a Core Class
Monday, July 15th, 2013
You want to add colors to the
UIColor class. There are currently 15 different preset colors that can be used, but that's not good enough for you. You REALLY like yellow, and just
yellowColor isn't going to cut it. You also want amber, aureolin, and citrine (thanks, Wikipedia). Instead of memorizing the RGB values and using them with
colorWithRed every time, you want to be able to reference them by name with
This is a perfect task for categories. Let's open Xcode. We'll start with a plain vanilla Single View Application:
Hit the "Next" button. Enter whatever you fancy for the product name, check "Use Storyboards" and "Use Automatic Reference Counting". Keep "Include Unit Tests" unchecked. When the project is ready to go, hit "Next" to create the project and create a new file with ⌘ + N. We're going to create an Objective-C category by navigating to Cocoa Touch in the left pane of the New File Window and selecting "Objective-C category":
In the "Category" field, enter something descriptive of what we're creating, perhaps "MoreYellow". The "Category on" field is more important. This is the class we will be adding functionality to. Begin typing "UIColor" and it should autocomplete for you:
If they're not already in there, go ahead and drag and drop these new "UIColor+MoreYellow.h" and "UIColor+MoreYellow.m" files into the "Supporting Files" folder for organizational purposes.
In our "UIColor+MoreYellow.h" file, we'll create the function prototype for the first new shade of yellow we want:
Notice this function has a
+ in front of it to denote it is a class method. Class methods are called upon a class instead of an instance variable of a class. What does this mean? Time for a little diversion.
Let's say we're setting the background color of our view. We would do this with the following:
self.view.backgroundColor = [UIColor redColor];
self is the current ViewController we are working with.
redColor is a message being sent to (or a "method being called upon") the
Now let's say we want to get the number of items in an array. There is a message called
count that will do this for us. However, we can't send the
count message directly to the
NSArray class because the
NSArray class itself does not hold any items. It is merely a blueprint for
NSArray instances (or "objects"). Only instances of
NSArray can hold items. We could do the following:
NSArray *items = [[NSArray alloc] initWithObjects: @"first item", @"second item", nil]; NSLog(@"%d", [items count]);
Incorrect - the
NSArray class itself doesn't hold any items.
NSLog(@"%d", [NSArray count]);
count is a message being sent to
items, which is an instance of the
NSArray class. In this case,
count will return the value 2.
%d is the specifier for integers, which is what the
count method returns (specifically a
NSUInteger, or unsigned integer).
We just declared the function in "UIColor+MoreYellow.h". Now let's define the function in "UIColor+MoreYellow.m".
The RGB value for amber is (255, 190, 0). Because the
colorWithRed method takes float values between 0 and 1, we have to divide our red, green, and blue values by 255.0. The red value is 255.0/255.0 = 1.0. The green value is 190.0/255.0. The blue value is 0/255.0 = 0.
We'll repeat this process in the .h and .m files for
citrineColor using the appropriate RGB values:
We can now reference these colors in our ViewController.m file by simply importing "UIColor+MoreYellow.h":
backgroundColor of our view is set to a random yellow color. The
arc4random_uniform() function is the most true random number generator in Objective-C. Other functions such as
arc4random() give results that are biased around powers of 2.