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”) } }
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!.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.