Thursday, April 28, 2016

Objective C Extensions

Before going to the topic, Let's see some real time scenarios we come across where we need this topic :)

I need a class property to be readonly to outside world but should be readwrite inside my class.
I need local variables but I don't want to expose them to outside of my class.

Let's discuss these requirements with a practical example in real time.


                         



I have a Employee class here having two properties.

  • salary
  • isTaxApplicable



     
#import

     @interface Employee: NSObject
      {

      }

        @property(nonatomic,assign) int salary;
        @property(nonatomic,readonly) BOOL isTaxApplicable;

        -(id)init;

    @end




#1 : I need a class property to be readonly to outside world but should be readwrite inside my class.


In Employee class, isTaxApplicable depends on salary value. Obviously I need to make isTaxApplicable property as readonly to outside world. Whereas, It should be readwrite inside my Employee class.

Here comes the concept called Extensions. In the implementation file (.m file) of the class, We can write the extension as shown below. 



  #import "Employee.h"

  @interface Employee ()

  @property(nonatomic,readonly) BOOL isTaxApplicable;

  @end


Here we can change the access level of a property. I have given the readonly access level in the header file and in the implementation, I have changed the access level to readwrite.

Now I can write isTaxApplicable property inside my class.

This is one of the uses of Extensions, Where we can change the access level of a property. Outside of this class can only read the property, they can write to it.


                         




#2 : I need local variables but I don't want to expose them to outside of my class.


We may need some temporary variables inside our class while implementing the business logic inside our class. But, we don't want them to be visible to outside world though they can't access it. In this case also, instead of keeping these temp variables in the header file, we can keep them in the extensions inside our implementation file as shown below.



  #import "Employee.h"

  @interface Employee () {

      int tempCounter;
      NSArray *tempArray;

  }

  @property(nonatomic,readonly) BOOL isTaxApplicable;

 @end


If you ask me,

why can't we keep them in the header file it self?

My answer is,

Let's say you are doing a static library where only header files in the library are visible. In this case keeping the temporary variables which outside of your class can't access doesn't look good. Why because, they don't need those. In fact they can't use those. So keeping those type of variables inside the extensions looks good and fine. Agree?


#3 : I need to go for a private API


If we want a method to be a private method, We can implement that in the implementation file so that It is not visible to outside world including the sub classes. For one or two methods it is fine. But, What If we have huge number of private methods?
If we implement all in the implementation file with out defining them any where, It is hard to know the private methods in the implementation file.

For this, We can create a private API using the Extensions. We can define all the private methods in the Extension of a class. If we don't implement these methods in the implementation file, Compiler will give a warning as well. Looking at the extension , We can see all the private methods inside a class. For one two methods, there is no need of this API, Where as for huge number of methods, It helps us a lot.



  #import "Employee.h"

  @interface Employee () 
   {

      int tempCounter;
      NSArray *tempArray;

   }

  @property(nonatomic,readonly) BOOL isTaxApplicable;

  /****   Private API   ******/

  -(void)privateMethod1;

  -(NSString*)privateMethod2;

  -(BOOL)privateMethod3:(int)val;

  @end



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