Monday, June 6, 2016

static variables in Objective C

A variable declared as static will always point to the same address location irrespective of how many time we refer it.


A variable can be made a static variable by prefixing it before the data type (here data type is int) with 'static' keyword.


Let's take a static variable inside a method.



   - (int)currentEvenNumber{
    
        static int evenNumber = 0;

        evenNumber += 2;
    
        return evenNumber;
    

    } 


'currentEvenNumber' method gives me every time an incremental even number.



    [self currentEvenNumber];   //2
    [self currentEvenNumber];   //4
    [self currentEvenNumber];   //6

    [self currentEvenNumber];   //8


This means, Once stated a variable as static, It will get initialized only once and points to the same memory address thereafter every time. 


The scope of this 'evenNumber' static variable is with in the 'currentEvenNumber' method. We can not access this static variable out side of that method.


If we need the scope of a static variable to be entire class, We should declare it in the beginning of class implementation after the import statements.


Let's take a real time use case and discuss in detail. Suppose we need to know every time we initialize and deinitialize an object, We need the remaining number of that particular class instances in memory. 


                         




I am taking a class named 'Parent'. I want to know the remaining instances of this class every time I initialize and deinitialze objects of this class. For that, I have taken a class method 'totalInstancesInMemory', Which returns me the remaining instances number. As this number is class specific, We don't want objects of this class to access it. So I made it a class method.



   @interface Parent : NSObject

     +(int)totalInstancesInMemory;


   @end


As I said, I am taking two static variables at the beginning of 'Parent' class implementation so that the scope of those static variables will be entire class.


  
  #import "Parent.h"

  static int numberOfInitializations = 0;
  static int numberOfDeinitializations = 0;


  @implementation Parent



'numberOfInitializations' is for storing total number of initializations.
'numberOfDeinitializations' is for storing total number of deinitializations.

Initially, these values are 0.

In the init method of class, I need to increment the 'numberOfInitializations' value.



  -(id)init{
    
      self = [super init];
    
      if (self != nil)
      {
          [Parent numberOfInitializations];
      }
    
      return self;
  }


  +(int)numberOfInitializations{

      numberOfInitializations ++;

      return numberOfInitializations;
    

  }


In the dealloc method of class, I need to increment the 'numberOfDeinitializations' value.



  +(int)numberOfDeinitializations{

      numberOfDeinitializations ++;

      return numberOfDeinitializations;

  }

  - (void)dealloc{
    
      [Parent numberOfDeinitializations];


  }


With this code, the respective counters will get incremented whenever there is an initialization and a deinitialization of an instance of the class.

Here comes our use case method.



  +(int)totalInstancesInMemory{
    
      int remainingInstances = [Parent numberOfInitializations
                                                        - [Parent numberOfDeinitializations];
    
      NSLog(@"totalInstancesInMemory : %d", remainingInstances);
    
      return remainingInstances;


   }


At any point of time, total number of instances of a class is equal to,

totalInstancesInMemory = numberOfInitializations - numberOfDeinitializations;



    [Parent totalInstancesInMemory];   //totalInstancesInMemory = 0
    
    Parent *p1 = [[Parent allocinit];
    
    [Parent totalInstancesInMemory];  //totalInstancesInMemory = 1
    
    Parent *p2 = [[Parent allocinit];
    
    [Parent totalInstancesInMemory];  //totalInstancesInMemory = 2
    
    p1 = nil;
    
    [Parent totalInstancesInMemory];  //totalInstancesInMemory = 1
    
    p2 = nil;
    
    [Parent totalInstancesInMemory];  //totalInstancesInMemory = 0
    
    Parent *p3 = [[Parent allocinit];
    

    [Parent totalInstancesInMemory];  //totalInstancesInMemory = 1

    


                         


Like that there will be so many use cases we may across in real time where these static variables come into picture and makes our life easy.


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