Categories in Objective-C

   Posted by: Jason Shapiro

Typically, when a developer wants to extend or modify the behavior of a class in an Object Oriented language, inheritance is used.  While Objective-C does support inheritance, it also offers an alternative syntax: "Categories."

The easiest way to conceptualize a category is to think of it as a short cut to add extra methods to an existing class.  This is the key difference between inheritance and categories: inheritance allows you to override methods, add new methods, and add new instance variables / properties; a category is more limited: you cannot create new instance variables / properties... only methods are permitted.

Let's compare and contrast the two with a simple code example.  Let's say I want to add a method to the NSArray class that returns all of the text in an array, as uppercase Strings.  I could try extending NSArray:

   1: @interface StringArrayUpperCaser : NSArray
   2: -(NSString *)stringAtIndexToUpperCase:(NSInteger)index;
   3: @end
   1: #import "StringArrayUpperCaser.h"
   2:  
   3: @implementation StringArrayUpperCaser
   4: -(NSString *)stringAtIndexToUpperCase:(NSInteger)index
   5: {
   6:   NSString *theString = [self objectAtIndex:index];
   7:   return [theString uppercaseString];
   8: }

Unfortunately, I'd find out pretty quickly that I'd need to do a bit more work.  There are certain methods that are required to be overridden in all subclasses of NSArray (not to mention other overrides that would be required to make convenience methods such as "arrayWithObjects" to work properly).

Given that all I wanted to do was add one method to NSArray, this is starting to look like a lot more work than I had bargained for.  So let's try an alternative solution: creating a category.  This process is relatively straight forward.  You'll create an interface and implementation, just as you would with a normal class, however you put the name of your category in parenthesis (to the right of the class name you are enhancing):

   1: @interface NSArray (StringToUpperCase)
   2: -(NSString *)stringAtIndexToUpperCase:(NSInteger)index;
   3: @end
   1: #import "NSArray+StringToUpperCase.h"
   2:  
   3: @implementation NSArray (StringToUpperCase)
   4: -(NSString *)stringAtIndexToUpperCase:(NSInteger)index
   5: {
   6:   NSString *theString = [self objectAtIndex:index];
   7:   return [theString uppercaseString];
   8: }
   9: @end

The convention for naming the physical files is typically <Class Name>+<Category Name>.  In this case, we'd name the files NSArray+StringToUpperCase.h and NSArray+StringToUpperCase.m

Now, when I want to use this new method, I import the category and simply call it on a pointer for an NSArray object:

   1: #import "NSArray+StringToUpperCase.h"
   2:  
   3: int main (int argc, const char * argv[])
   4: {
   5:   @autoreleasepool 
   6:   {
   7:     NSArray *myArray = [NSArray arrayWithObjects:@"this", @"is", @"a", @"test.", nil];
   8:     for( NSInteger i = 0; i < [myArray count]; i++ )
   9:     {
  10:       NSLog(@"%@", [myArray stringAtIndexToUpperCase:i]);
  11:     } 
  12:   }
  13:     return 0;
  14: }

results

You'll note that although we named our categories in the interface / implementation ("StringToUpperCase"), we did not have to reference the category name when using the new method.  All we had to do was create an NSArray object and send the new message.

If you happen to see the following warning ("... may not respond to..."), double check to make sure you imported the category's header file.

category-warning

Besides easing sub-classing requirements, Categories can help with organizations: large classes can be separated into different files, based on functionality.  For example, you may have a SystemManager class that does 'read', 'create', and 'manipulate' functionality.  You could have the core methods declared in the SystemManager class, and create categories for each of the separate specific functionalities: SystemManager (read), SystemManager (create), SystemManager (manipulate).  You could also use categories to separate your deprecated methods from the rest of your class: SystemManager (deprecated).

In summary, Categories are a handy way for quickly extending or modifying the behavior of a class, while also offering benefits in terms of logical organization.


Comments (4)

Web Designer 12/1/2011 2:51 AM

Give me time to read all the comments, but I really enjoyed the article. It proved to be Very helpful to me and I am sure to all the commenters here! It’s always nice when you can not only be informed, but also entertained! I’m sure you had fun writing this article.

Authentication and Permissions 12/20/2011 1:23 PM

it's useful information for users of C++ object oriented programming for their task and it's related to class declaration in existing class and good information between inheritance and category define while crating class.

solar power systems 1/4/2012 11:17 PM

I really love the way information is presented in your post.

solar power systems 1/18/2012 11:56 PM

Really great post..Thank you for sharing This knowledge.Excellently written article by whom is there any other blog?

Add a Comment

*

*

Loading

Find Us
Contact Us 651-288-7000 1-800-866-9884
Home | Training | Curriculum | Course Finder | Schedule | Enroll | Twin Cities Java User Group | Consulting | Foundation | Jobs | About Us | Our Story | Press Room | Instructors | President | Map & Directions | Sitemap

Java Training | JSF / Struts / Spring / Hibernate Training | Java Power Tools Training | .NET 4.0 & Visual Studio 2010 Training | Microsoft Web Development Training | Prism / MVVM / MEF Training | .NET 3.5 and Visual Studio 2008 Training | .NET 2.0 and Visual Studio 2003 Training | Cloud Computing Training | Ajax / Web Services / XML Training | Groovy and Grails Training | SQL Server 2012 Training | SQL Server 2008 Training | SQL Server 2005 Training | Mobile Development Training | SharePoint 2010 Training | SharePoint 2007 Training | Agile, Process, Analysis & Design Training | Arch/Design Patterns Training | Microsoft Official Curriculum Training | Web Development Training | Ruby Training | Rational Application Developer (RAD) Training | WebSphere Application Server Training | WebSphere Portal Training | WebLogic Training | Boot Camp Training | Project Management Training | C / C++ Training | Metro / WinRT / Windows 8 Development Training | Retired

Intertech delivers training on-site and virtually serving cities including Phoenix, AZ | San Francisco, CA | Los Angeles, CA | San Diego, CA | San Jose, CA | Washington, DC | Chicago, IL | Orlando, FL | Boston, MA | Duluth, MN | Minneapolis St. Paul, MN | Rochester, MN | Raleigh-Durham, NC | New York, NY | Philadelphia, PA | Austin, TX | Dallas, TX | Houston, TX | Seattle, WA.