Interview Questions: How memory management is handled on iOS?

Update: I'm working on a book that helps you ace iOS interviews. Sign up to the waitlist here:

This is another one of the blog posts in iOS Interview Questions series.

Memory management is very important in any application and especially so in iOS apps that have memory and other constraints. This is one of the standard questions asked in one form or another and it refers to ARC, MRC, reference types, and value types.

Expected answer:

Swift uses Automatic Reference Counting (ARC) which is conceptually the same thing as in Objective-C. ARC keeps track of strong references to instances of classes and increases or decreases their reference count accordingly when you assign or unassign instances of classes (reference types) to constants, properties, and variables. ARC does not increase or decrease reference count of value types because, when assigned, they are copied. By default, if you don't specify otherwise all the references will be strong references.

One of the gotchas of ARC to be aware of is Strong Reference Cycles. Under ARC for a class instance to be fully deallocated it needs to be free of all the strong references to it. But there is a chance you could structure your code the way that two instances strongly reference each other and therefore never let each other's reference count drop down to zero. There are two ways of resolving this in Swift: weak references and unowned references. Both of them will assign an instance without keeping a strong reference to it. Use weak keyword for one and unowned keyword for another before a property or variable declaration. Weak reference is used when you know that reference is allowed to become nil and unowned reference is used when you are certain that that reference has a longer lifecycle and will never become nil. Since weak references can have a value or can have no value at all they must be defined as optional variables. And unowned reference has to be defined as non-optional since it is assumed to always have a value.

Another important gotcha is Strong Reference Cycle in Closures. When you use closures within a class instance they could potentially capture self in them and if self, in turn, retains that closure than you'd have a mutual strong reference cycle between closure and class instance. It often occurs when you use lazy loaded properties, for example. To avoid that you'd use the same keywords weak and unowned. When you define your closure you should attach to its definition a so called capture list. A capture list defines how the closure would handle references captured in it. By default, if you don't use a capture list everything will be strongly referenced. Capture lists are defined either on the same line where the closure open bracket is or on the next line after that. They defined with a pair of square braces and each element in it has weak or unowned keyword prefix and is separated by commas. The same thinking as with variable references applies to closure capture list - define a capture variable as a weak optional if it could become nil at some point and the closure won't be deallocated before then, and define captured reference as unowned if it will never become nil before the closure is deallocated.

Red flag:

This is a must know for every iOS developer! Memory leaks and app crashes are all too common due to poorly managed memory in iOS apps.

Update: I'm working on a book that helps you ace iOS interviews. Sign up to the waitlist here:

comments powered by Disqus