Ans :
According to ARC, variable should be one of three Strong, Weak or unowned. By default, variable has strong reference.
Let's take example :
class Employee {
var name : String
var emid : String
var title : String
init(name: String,emid: String, title: String) {
self.name = name
self.emid = emid
self.title = title
}
deinit {
print("Employee : \(name) removed")
}
}
var manan : Employee? = Employee(name: "Manan", emid: "1234", title: "Sr iOS Developer")
manan = nil
Here deinit will be called and output will be "Employee Manan removed"
Now we add reference :
var sagar = manan
manan = nil
Here deinit will not be called due to adding reference. Here sagar has strong reference to variable which owned by manan before.
Now,
var sagar = manan
manan = nil
sagar = nil
Here deinit will be called and again output will be "Employee Manan removed"
Now let's discuss about Strong cycle :
Strong cycle occurs when two object has strong reference to each other. i.e objectA has strong reference to objectB and objectB has strong reference to objectA.
example :
class Employee {
var name : String
var emid : String
var title : String
var macBook : MacBook?
init(name: String,emid: String, title: String) {
self.name = name
self.emid = emid
self.title = title
}
deinit {
print("Employee : \(name) removed")
}
}
class MacBook {
var serialNumber: String
var assignee : Employee?
init(serialNumber: String) {
self.serialNumber = serialNumber
}
deinit {
print("Macbook : \(serialNumber) removed")
}
}
var manan : Employee? = Employee(name: "Manan", emid: "1234", title: "Sr iOS Developer")
var mac : MacBook? = MacBook(serialNumber: "ABC123")
manan?macBook= mac
manan = nil
mac = nil
Here, output :
Employee Manan removed
Macbook ABC123 removed
Why? Because here there is no strong reference from both side. So retain cycle is not yet created.
Now,
var manan : Employee? = Employee(name: "Manan", emid: "1234", title: "Sr iOS Developer")
var mac : MacBook? = MacBook(serialNumber: "ABC123")
manan?macBook= mac
mac?.assignee = manan
manan = nil
mac = nil
Output will be :
Nothing will be removed. Not output comes. Because of retain cycle. So there are strong relationship between both objects like manan has mac and mac is assigned to manan.
So, if we want to solve this problem we have to use weak or unowned reference for one side.
So,
weak var assignee : Employee?
Now output will be :
Employee Manan removed
Macbook ABC123 removed
So Now unowned : It is same as weak as it does not hold strong relationship with object. So when to use unowned : An unowned reference is used when the other instance has the same lifetime or a longer lifetime.
Difference between weak and unowned :
According to ARC, variable should be one of three Strong, Weak or unowned. By default, variable has strong reference.
Let's take example :
class Employee {
var name : String
var emid : String
var title : String
init(name: String,emid: String, title: String) {
self.name = name
self.emid = emid
self.title = title
}
deinit {
print("Employee : \(name) removed")
}
}
var manan : Employee? = Employee(name: "Manan", emid: "1234", title: "Sr iOS Developer")
manan = nil
Here deinit will be called and output will be "Employee Manan removed"
Now we add reference :
var sagar = manan
manan = nil
Here deinit will not be called due to adding reference. Here sagar has strong reference to variable which owned by manan before.
Now,
var sagar = manan
manan = nil
sagar = nil
Here deinit will be called and again output will be "Employee Manan removed"
Now let's discuss about Strong cycle :
Strong cycle occurs when two object has strong reference to each other. i.e objectA has strong reference to objectB and objectB has strong reference to objectA.
example :
class Employee {
var name : String
var emid : String
var title : String
var macBook : MacBook?
init(name: String,emid: String, title: String) {
self.name = name
self.emid = emid
self.title = title
}
deinit {
print("Employee : \(name) removed")
}
}
class MacBook {
var serialNumber: String
var assignee : Employee?
init(serialNumber: String) {
self.serialNumber = serialNumber
}
deinit {
print("Macbook : \(serialNumber) removed")
}
}
var manan : Employee? = Employee(name: "Manan", emid: "1234", title: "Sr iOS Developer")
var mac : MacBook? = MacBook(serialNumber: "ABC123")
manan?macBook= mac
manan = nil
mac = nil
Here, output :
Employee Manan removed
Macbook ABC123 removed
Why? Because here there is no strong reference from both side. So retain cycle is not yet created.
Now,
var manan : Employee? = Employee(name: "Manan", emid: "1234", title: "Sr iOS Developer")
var mac : MacBook? = MacBook(serialNumber: "ABC123")
manan?macBook= mac
mac?.assignee = manan
manan = nil
mac = nil
Output will be :
Nothing will be removed. Not output comes. Because of retain cycle. So there are strong relationship between both objects like manan has mac and mac is assigned to manan.
So, if we want to solve this problem we have to use weak or unowned reference for one side.
So,
weak var assignee : Employee?
Now output will be :
Employee Manan removed
Macbook ABC123 removed
So Now unowned : It is same as weak as it does not hold strong relationship with object. So when to use unowned : An unowned reference is used when the other instance has the same lifetime or a longer lifetime.
Difference between weak and unowned :
- weak reference is used where there is possibility for that reference to become nil at some point during its lifetime.
- An unowned reference is used where there is no possibility for that reference becoming nil at any point until the self-object exist.
Example :
Every employee may or may not hold ICard but every ICard must be assigned to some one.
So Employee class has ICard variable as optional, but in ICard class, employee variable with optional and weak is not possible. If we want to use weak, we should make employee variable in ICard class optional. But we don't want that.
So, solution is that :
unowned var employee : Employee
Now we are cleared about strong, weak and unowned and also our question : Retain Cycle or Strong Cycle.
Credit : Vinod Shwami