Retain Cycle in Swift.
Each time you create a new instance of a class ARC allocates memory to store information about it(an i.e type of instance, a property value of instance), and automatically free this memory when that instance is no longer in need or reference count is zero.
What is the retain cycle
Retain Cycle is the condition When 2 objects keep a reference to each other and are retained, it creates a retain cycle since both objects try to retain each other, making it impossible to release.
ARC has been helping a developer in memory management. developer no need to do anything.
Except for 3 cases were you need to specify the relationship between the object to avoid Retain Cycle.
- Strong Reference Cycles Between Class Instances
- Strong Reference Cycles for delegate
- Resolving Strong Reference Cycles for Closures
1. Strong Reference Cycles Between Class Instances
Problem:
As we know that variable is point strongly to the instance
let’s begin with the following example. In that Owner and Home are pointing to each other.so retain cycle is occurred.
Here’s a visual representation of what a strong reference cycle may look like:
So Owner()
and Home()
an instance reference count is one. On next level home and owner instance point strongly to each other.
Now Owner()
and Home()
an instance reference count is two.
In Program (Example 1.0) at line 38, 39 we have set the owner and home instance to nil. so reference count of will is one for both.
when we assign nil to the object ARC decrement the count
Now both instance reference count is still one even we set both instances to nil. We can see the owner and home instance will never release from memory. Because both instance still strongly point to each other.
Solution:
To avoid the retain cycle we have to set the relation between object either weak or unowned
In Weak object reference count is never increase, unlike strong. Weak is optional type they may contain an actual object or nil.
In unowned object reference count is never increase, like weak. but unowned object never nil it expected the actual object.
Generally, child object should point weakly to the parent object.
In Program 1.0 at line 18, We can set a weak attribute for owner property of Home().
As we can see a property of Home()
is point weakly to the Owner()
instance.So Owner()
a reference count is one it's not increased due to a weak reference.
In diagram (Example 1.0) at line 38. we have set the address
variable to nil so Owner()
a reference count is 0. As soon as reference count is reached to zero object get deallocated from memory. hence Home()
a reference count is reached to one
same for line 39.we have set the john
variable to nil.hence Home()
a reference count is reached to zero. then object get deallocated from memory
2. Strong Reference Cycles for delegate
Problem :
First, we have a protocol called, HomeDataProtocal.
Second, we have class Home with property (i.e delegate) whose type is HomeDataProtocal?.
A class Owner has implemented the protocol i.e HomeDataProtocal.
Class Owner has a property, home.
Second, home is an instance of Home. Class Home has a property, delegate.
I’ve made a simple graph for you to visualize.
If you attempt the following code below, nothing happens.
There is a strong reference between Owner and Home instance.
Solution :
The only thing that we need to do is, put weak in front of var delegate and import class in HomeDataProtocal . because ‘weak’ must not be applied to non-class-bound ‘HomeDataProtocal’; consider adding protocol conformance that has a class bound
Let’s see how it looks now.
Now lets once again nil the john
Yeah we did it☺️
3. Strong Reference Cycles for Closures
Closures can cause retain cycles for a single reason: by default, they have a strong reference to the object that uses them.
We can assume that there are two different entities i.e Owner instance and closure.
Problem:
Let us visualize.
If you attempt the following code below, nothing happens.
Be default closure property has a strong reference to its block.
Solution :
There is one way for us to set the relationship “weak” from the closure block to the object (self). Let us introduce capture lists.
Closure block has a weak reference to object, thus the property as well.
The self (object) became an optional type based on self?.name. Here is why. The closure should be able to break the strong reference because the relationship is weak. Therefore, Swift automatically converts the type of self as an optional or actual type.
Hence relationship from owner closure to owner instance is weak so the reference count of owner instance will be one. because in weak relationship object retain count will not increase.
If you attempt the following code below, nothing happens.
In program 1.3 at line 108, we have set the address variable to nil so the owner instance retains count decrease by one. Now it’s reached to zero. So ARC detects the object retain count is zero so owner instance will deallocate from memory.
hence closure reference reached to zero so it’s also got deallocate from memory.
In next article we will see the difference between weak and unowned.