Memory Management in Swift with Strong, Weak and Unowned Reference

Author - Nilesh Kikani

For iOS app its crucial to learn memory management. Either you are using Objective C or Swift but you need to be familiar with how memory management will be helpful. To begin with this article I will presume you have some knowledge of Objective C as well as Swift and clear concept  of OOP, closures, optionals and properties.

Basically memory management is reference counting, In Objective C or Swift when you reference variable in code its retain count increased and visa-versa. Variable gets deallocated if its retains count reach to 0.

You already knows that swift uses ARC(Automatic Reference Counting) to mange memory usage of your app. So you need not to worry about memory management yourself. However you need to require knowledge to manage memory in your code to avoid memory leaks.

What is ARC and how does it work for memory management?

When you create any new instance of variable, ARC allocates memory to store information, when variable no longer needed ARC frees up memory assigned to that instance. You need to be sure that once variables gets deallocate, it’s not possible to access that again otherwise your app will crash.

Init() called while you initialise any variable or object,  while reference count of object reach to 0, deinit() called to deallocate the object or variable. Below I have written sample code for better understanding. Actually deinit block run automatically by ARC but for better understanding I have written it here in below code.

import Foundation
class Cat {
    let name: String
    init(name: String) {
        self.name = name
        print(“\(name) is being initialized”)
    }
    deinit {
        print(“\(name) is being deinitialized”)
    }
}
To understand ARC you need to learn terms Strong Reference, Weak Reference and Unowned Reference. In this article you will learn each in detail.

Strong Reference

With Swift while you define property, strong reference applied default. Strong reference almost used everywhere in Swift. Each new created object of a class have reference counter.  Which will get increase once you assign property of value to object. Until value of reference counter is greater than 0 it won’t get deallocated. Let’s consider below two classes :

class Person {
    let name: String
    init(name: String) { self.name = name }
    var cat: Cat?
    deinit { print(“\(name) is being deinitialized”) }
}
class Cat {
    let unit: String
    init(unit: String) { self.unit = unit }
    var person: Person?
    deinit { print(“Cat \(unit) is being deinitialized”) }
}

For both classes have a name and optional property – cat for Person, because every person may not have a cat, and a person for a car, because a cat may not always have a owner.

Lets creates instance of both class and assign reference counter to 1 for both.

var john: Person ?
var tom: Cat?
John = Person(name: “John”)
Tom = Cat(uniName: “Tom”)
John and Tom have strong reference to the Person and Cat object respectively. Now if you want to assign strong reference lets link two object together like below.
John!.cat = tom
john!.person = john

This increase reference counter to 2 now. If you want to break strong reference cycle of john and tom lets assign nil value to object instance but this will not reset reference counter to 0. So ARC will not able to deallocate these objects due to retain cycle.

John = nil
Tom = nil

Weak Reference

It allows to create instance but don’t increase the reference count of ARC. Mostly reference should be marked as a weak and having shorter lifetime than other types of reference. If their reference is set to nil, we should use Weak reference. If no other instance have a strong reference to instance, instance will deallocate. Lets consider above example to resolve issue of strong reference cycle.

class Person {
    let name: String
    init(name: String) { self.name = name }
    Weak var cat: Cat?
    deinit { print("\(name) is being deinitialized") }
}

class Cat {
    let unit: String
    init(unit: String) { self.unit = unit }
    Weak var person: Person?
    deinit { print("Cat \(unit) is being deinitialized") }
}

Now ARC is able to deallocate all objects correctly. If you will write weak either Person or Cat it will work perfectly for ARC deallocation and fix strong reference cycle.

Unowned Reference

Its same like Weak reference, retain counter doesn’t increase by one. Unlike weak references Unowned don’t have to be optional because they aren’t automatically set to nil on deallocation. Please use unowned reference only if you know that object will never be nil for that instance. Let’s consider below closure with Unowned reference.

class Person {
    var car: Car?
}

class Car {
    unowned var person: Person

    init(person: Person) {
        self.person = person
    }
}

Note : Use weak reference whenever you know that it will become nil at some point. Same use Unowned reference when you know that its reference will never never be nil once its initialised.

Finally, if you don’t manage your memory then its make your application unstable with lots of memory leaks. But with careful use of weak and unowned we can manage memory leaks and abandon memory.

Don’t miss the next post!

Loading

Related Posts