Retain Cycle in Swift.

Shantaram Kokate
6 min readMar 15, 2019

--

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.

  1. Strong Reference Cycles Between Class Instances
  2. Strong Reference Cycles for delegate
  3. 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.

Example 1.0

Here’s a visual representation of what a strong reference cycle may look like:

Memory Allocation For Instance

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.

Retain Strong reference cycle and memory leak

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.

Weak Relationship

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.

var john = nil // not deallocated

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

weak in front of var delegate
import class in HomeDataProtocal

Let’s see how it looks now.

Now lets once again nil the john

var john = nil // deallocated

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.

Program 1.3

Problem:

Let us visualize.

If you attempt the following code below, nothing happens.

var address = nil // not deallocate

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.

self become weak in block

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.

var address = nil // deallocate

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.

https://medium.com/@35df9d65780f/f93ab5079025?sk=

--

--