Tuesday, May 3, 2016

Objective C Categories

Categories were introduced in Objective-C If we want to add any new functionalities to the native classes as well as to our own custom classes.

If the above statement is sounding new to you, Please check my 
Objective C Subclass vs Category post, Which gives a clear idea to you on when to subclass and when to categorize.

Let's see some cases where we have to go for Categories instead of Subclassing by taking NSString class.

I want string reversal at various places in my application.
I want number of spaces in a string.


In this case, We have two options.


                         



#1 Write a subclass of NSString and add these two methods.



   @interface MyString : NSString

     - (NSString*)reverseString;
     - (int)numberOfSpaces;

   @end


If I subclass and write my custom methods, 

I need to import that subclass header file wherever I need those methods.
And I need to instantiate my subclass everywhere to use those methods.



  MyString *str = [MyString alloc] init];

  NSString *reverseStr = [str reverseString];

  int numberOfSpaces = [str numberOfSpaces];


Isn't it painful for a matter of adding two new methods writing a sub class and using it?

What if there is something which allows us to add these two new methods in the scope of native class itself and allows us to call directly using NSString object.

Sounds great?

#2 Categories


In your Xcode editor, Go to,

 File -> New -> select 'Objective-C File' 

You will be getting,

File : Enter the category name of your choice. In my case it is 'Additions', as there are additions to NSString.
File Type : Category
Class : The base class for our categorization. In our case, It is NSString.

NSString+Additions.h and
NSString+Additions.m 

will get created in your project.

The file names them self convey the reason behind their creation. We have taken those files to add our custom functionality to the NSString class. So wherever we need those new custom methods, We need to import
NSString+Additions.h file.

Let's add our custom methods now.

NSString+Additions.h




  #import

  @interface NSString (Additions)

    - (NSString*)reverseString;
    - (int)numberOfSpaces;

  @end



Whatever the category name we have given in the File box, appears in the brackets.
Here, NSString (Additions)You can keep your own name. 


NSString+Additions.m 




 #import "NSString+Additions.h"

 @implementation NSString (Additions)

 - (NSString*)reverseString{
    
    NSMutableArray *strArr = [[NSMutableArray allocinit];
    
    //taking all the characters of the string into an array
    
    for(int i=0;i<self.length;i++){
        
         char c = [self characterAtIndex:i];
         NSString *character = [NSString stringWithFormat:@"%c",c];
         [strArr addObject:character];
        
    }
    
    //forming a reverse string by looping the array starting from the last object
    
    NSMutableString *mstr = [[NSMutableString allocinitWithString:@""];
    
     for(int i=strArr.count-1; i >= 0; i--){
          [mstr appendString:[strArr objectAtIndex:i]];
     }
    
     return [mstr copy];
    
 }

 - (int)numberOfSpaces{
    
     NSArray *strArr = [self componentsSeparatedByString:@" "];
     return strArr.count-1;
 }

 @end



They could be a better logic for string reversal.
Please ignore my logic for reversing a string though it's working :)




                         


We have added our required custom methods to the NSString class. Let's see how to access them.

Wherever you need these methods, import NSString+Additions.h file and you can access them as simple as the native NSString methods as shown in the below example.



    NSString *blogName = @"iOS Solves Blog";
    NSString *reverseName = [blogName reverseString];
    
    NSLog(@"reverseName : %@",reverseName);  // reverseName : golB sevloS SOi
    
    int numberOfSpaces = [blogName numberOfSpaces];
    

    NSLog(@"numberOfSpaces : %d",numberOfSpaces); //numberOfSpaces : 2


Hope this post is useful. Feel free to comment incase of any queries.