Showing posts with label mutable. Show all posts
Showing posts with label mutable. Show all posts

Thursday, July 5, 2018

Swift Closures Capture List


In this tutorial Let’s see how closure takes the variables in the context.


       
 var fruit = "Apple"

  let closure = {
      return fruit
  }

  print("\(closure())")  //Apple

  fruit = "Banana"

  print("\(closure())")  //Banana



In this case, closure takes fruit as reference. I mean, If we change the value of fruit and call closure again, We see the new value.

Closures by default take reference and use the values.

Now, What If we don’t need any new values for closure?

We can add capture list like shown below.


       
 var fruit = "Apple"

  let closure = { [fruit] in
      return fruit
  }

  print("\(closure())")  //Apple

  fruit = "Banana"

  print("\(closure())")  //Apple



[fruit] in is nothing but a capture list which creates immutable copies.

Here fruit will be passed as an immutable copy to the closure. Means, though we change the value of fruit, As closure captured immutable copy of fruit, The new value will not get reflected.

As it is an immutable copy, If we try to change the value inside closure, We will get compiler warning.


       
 var fruit = "Apple"

  let closure = { [fruit] in
      fruit = "Mango"   //Compiler warning!
      print("\(fruit)")
  }

  closure()  //Apple

  fruit = "Banana"

  closure()  //Apple


  Playground execution failed:

  error: closure.playground:16:11: error: cannot assign to value: 'fruit' is an immutable capture
    fruit = "mango"
    ~~~~~ ^



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



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.


Friday, September 18, 2015

Objective C copy and mutableCopy

In Objective C, there are mutable versions for basic data types as shown below.


Data TypeMutable
NSArrayNSMutableArray
NSSetNSMutableSet
NSDictionaryNSMutableDictionary
NSStringNSMutableString

The use of these mutable versions is, they are dynamic in nature. Means, we can add/edit and delete items from those mutable versions.


                         



For example, if we declared an array like this.

NSArray *fruits = [[NSArray alloc] initWithObjects:@"apple",@"orange",@"grape",nil];

That's it, we can't edit (insert, delete, add) this array at run time.

It won't work out if we need to play around with an array of elements at run time. If we need to edit the items in an array at run time, we need to go for the mutable one which is NSMutableArray.

NSMutableArray *mutableFruits = [NSMutableArray alloc] init];

After the above initialisation, the count of mutableFruits array is 0. Now, we can add elements to this array as shown below.

[mutableFruits addObject:@"grapes"];
[mutableFruits addObject:@"apples"];
[mutableFruits addObject:@"bananas"];
[mutableFruits addObject:@"oranges"];

We can remove elements as shown below.

[mutableFruits removeObjectAtIndex:1];
[mutableFruits removeAllObjects];

If you observe, it is very handy using mutable versions if the elements are dynamic at run time. Same applies for strings, sets and dictionaries.

Sometimes, we need to maintain both the versions like for example, I need basic fruits array across my application. But, at some point I need the mutable version of it to add or remove the items based on my functional requirement with out disturbing my basic array.

Here comes the concept of copy and mutableCopy. Let's see what copy does. 

NSArray *fruitsCopy = [fruits copy];

The above statement creates an exact copy of fruits array. That means, this copy returns the same NSArray, whose items we can't edit at run time.

Where as, 

NSMutableArray *fruitsMutableCopy = [fruits mutableCopy];

gives you the mutable version(NSMutableArray) of fruits array, whose content can be edited at run time.

Though the mutable versions are very useful, be careful while going for them as they occupy more memory than the normal ones until unless you specify exactly. So, go for them only you will have to edit their content at run time.

Thanks for reading this article. Hope you found it useful :)