Ghostboard pixel

Swift: weak and unowned

Swift: weak and unowned

With the keywords weak and unowned you can avoid so-called reference cycles. In this post we will discuss the differences between them.

References Cycles

As I’ve described already in my blog post “A Trick To Discover Retain Cycles”, it is still important to do some kind of memory handling, although ARC does most of the work for you:

First we are creating a RootViewController and a SecondViewController. The SecondViewController gets presented, if a button on the RootViewController is pressed. You can create this easily by using a segue in the storyboard of the app. Furthermore, there is a class called ModelObject, which has a delegate object of type ModelObjectDelegate. If the SecondViewController‘s view is loaded, the controller sets itself as the delegate of the ModelObject:

import Foundation

protocol ModelObjectDelegate: class {
    
}

class ModelObject {
    
    var delegate: ModelObjectDelegate?
       
}
import UIKit

class SecondViewController: UIViewController, ModelObjectDelegate {
    
    var modelObject: ModelObject?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        modelObject = ModelObject()
        modelObject!.delegate = self
    }
        
    @IBAction func closeButtonPressed(sender: UIButton) {
        dismissViewControllerAnimated(true, completion: nil)
    }
    
}

Ok, now let’s examine the memory handling: If we are dismissing the SecondViewController, the amount of used memory is not decreasing. But why is this? We would expect that with the dismiss of the SecondViewController memory gets deallocated. Let’s take a look at the objects. If the SecondViewController is loaded, it looks like this:

retainc1

Now, if the SecondViewController is dismissed, it looks like this:

retain2c

The RootViewController doesn’t have a strong reference to the SecondViewController anymore. However, the SecondViewController and the ModelObject have strong references to each other. And because of this they are not deallocated.

Weak

To avoid this behaviour, you can declare a reference as weak, which does not prevent ARC from deallocating the memory:

import Foundation

protocol ModelObjectDelegate: class {
    
}

class ModelObject {
    
    weak var delegate: ModelObjectDelegate?
    
}

The object graph looks now like this:

retainc3

Because there is just one strong reference between the SecondViewController and the ModelObject, there is no problem anymore in deallocating the memory.

Unowned

But instead of weak you can also use unowned. But what is the difference? If you are using weak, the property hast to be an optional, so it is allowed to become nil. If you are using unowned on the other hand, it must not be an optional. Since an unowned property is not an optional, its value has to be set in the init method:

import Foundation

protocol ModelObjectDelegate: class {
    
}

class ModelObject {
    
    unowned var delegate: ModelObjectDelegate
    
    init(delegate:ModelObjectDelegate) {
        self.delegate = delegate
    }
        
}

Depending on the property – optional or not – you have to choose between weak or unowned.

References

A Trick To Discover Retain Cycles
Optionals In Swift
Swift Programming Series (iBook Store)
Image: @ Fabrik Bilder / shutterstock.com