Showing posts with label dealloc. Show all posts
Showing posts with label dealloc. Show all posts

Wednesday, September 20, 2017

Swift 3 - weak and unowned references

To avoid, retain cycle we go with a weak reference in iOS.
In swift 3 we can go for weak or unowned to declare it as a weak reference.

In this post let’s see when to use weak and when to use unowned incase of 
closures and incase of normal property declarations.

weak always gives an optional, Where as unowned means we are sure like It is not going to be nil at any point of time.
If you are declaring something as unowned, Make sure It always will have a value.

Incase of Closures :-


------------------------------------------------------------------------------------------------------

DispatchQueue.main.async() { [unowned self] () in
      self.hideLoader()
}

------------------------------------------------------------------------------------------------------


In this block, I have used unowned reference for self, because I am sure like 
self can be never be nil when this block gets executed.

------------------------------------------------------------------------------------------------------

DispatchQueue.main.async { [weak self] in
    guard let strongSelf = self else { return }
    strongSelf.hideLoader()
}

------------------------------------------------------------------------------------------------------

In the above closure, I have taken self as weak and using that in my block. 
This means, self can be nil at any point of time.
So, Inside the block before using self, I am checking that with a guard statement.

From this, weak is an optional type whereas unowned is not.

Incase of Properties :-


Consider the following retain cycle. Person and Car created a retain cycle here.
The dealloc of both the classes will not get called here.

------------------------------------------------------------------------------------------------------

class Car {
    var driver:Person?
    deinit {
        print("Car dealloc")
    }
}

class Person {
    var car: Car?
    deinit {
        print("Person dealloc")
    }
}

var driver: Person? = Person()
var car: Car? = Car()

driver?.car = car!
car?.driver = driver!

car = nil
driver = nil

------------------------------------------------------------------------------------------------------

Car can exist without a driver and driver can exist without a car here.
To break this cyclic relationship, person can have a weak reference to his/her car as it is meaningful in this case.
(Person may not have a car, But Car should have a driver)

------------------------------------------------------------------------------------------------------

class Person {
    weak var car: Car?
    deinit {
        print("Person dealloc")
    }
}

------------------------------------------------------------------------------------------------------

Now the dealloc methods of Car and Person will get called as we have broke the retain cycle by giving a weak reference to car property of Person class.

This is the use case of weak reference.

Let’s see an use case of unowned reference.

Car can exist without a key, where as car keys existence is meaningless If that is not associated with a car.

------------------------------------------------------------------------------------------------------

class Car {
    var key:CarKey?
    deinit {
        print("Car dealloc")
    }
}

class CarKey {
    let car: Car
    init(car: Car) {
        self.car = car
    }
    deinit {
        print("CarKey dealloc")
    }
}

var car: Car? = Car()
var key: CarKey? = CarKey(car: car!)

car?.key = key

car  = nil
key = nil

------------------------------------------------------------------------------------------------------

We need to initialise a CarKey with a car instance always. So CarKey car instance can not be nil and it 
will always contain a value as we are initialising CarKey with always a car instance.

This also creates a retain cycle. In this case we can break this retain cycle with unowned as shown below.

------------------------------------------------------------------------------------------------------

class CarKey {
    unowned let car: Car
    init(car: Car) {
        self.car = car
    }
    deinit {
        print("CarKey dealloc")
    }
}

------------------------------------------------------------------------------------------------------

Conclusion As Per Apple Docs:-

Use a weak reference whenever it is valid for that reference to become nil at some point during its lifetime. Conversely, use an unowned reference when you know that the reference will never be nil once it has been set during initialization.


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


Wednesday, June 22, 2016

Executing a method only once though it is getting called multiple times at once in Objective C

In my static variables in Objective C post, We have discussed static variables. In this post, Let's see how can you avoid a method getting called at the same time more than once using these static variables. 

This can help some times,

  1. In case of multi threading, Where there is a chance of same method getting called at once.
  2. In case of a clash between your auto refresh and manual pull to refresh.

Let's solve the second scenario using the static variables.

In my application, I have a manual refresh of notifications using tableview's pull to refresh and also a 5 minute timer event to fetch the recent notifications and for that I am using the below method.



 - (void)fetchNotificationsFromServer{

     Server call to fetch recent notifications(
               
      );       

 } 


What If this is a clash between the manual and timer refresh?

Obviously, We will end up with duplicate notifications. To avoid this we can use the static variable funda as shown below.



 - (void)fetchNotificationsFromServer{

    static BOOL functionISExecuting = NO;

     if(!functionISExecuting){

         functionISExecuting = YES;

      }

    else
        
        NSLog(@"Fetching notifications from server is in progress.......");          
        return;
        
    }

     Server call to fetch recent notifications(

          functionISExecuting = NO;
               
      );
       


 }



As static variable value doesn't change with in the scope of the method, We can check that value whether the method is already being called and in progress or not. After the service call, whether the call is successful or failure, We can roll back the value so that the next method call will be successful.


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




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.