Blog / August 14, 2023 / 4 mins read / By Mahi Garg

Unowned vs Optional Unowned References in Swift

Memory management is a critical consideration in Swift development, and managing references is a key aspect of this. Two reference types that come into play are unowned and optional unowned references. Both are used to prevent strong reference cycles and manage memory efficiently. In this blog, we’ll delve into the differences between unowned and optional unowned references with examples to help you understand their applications.

Unowned References

An unowned reference is used when you are certain that the referenced object will never be nil during the lifetime of the reference. If you attempt to access an unowned reference after the referenced object has been deallocated, it will result in a runtime crash. Unowned references are great for situations where the lifetime of the referenced object is guaranteed.

Here’s an example to illustrate the usage of unowned references:

class Magazine {
    let title: String
    unowned let subscriber: Person
    
    init(title: String, subscriber: Person) {
        self.title = title
        self.subscriber = subscriber
        print("Magazine \(title) is initialized.")
    }
    
    deinit {
        print("Magazine \(title) is deallocated.")
    }
}

class Person {
    let name: String
    var magazineSubscription: Magazine?
    
    init(name: String) {
        self.name = name
        print("Person \(name) is initialized.")
    }
    
    deinit {
        print("Person \(name) is deallocated.")
    }
}

var person: Person?
var magazine: Magazine?

person = Person(name: "Alice")
magazine = Magazine(title: "Tech Today", subscriber: person!)

person = nil // Person Alice is deallocated
// Accessing magazine.subscriber now would lead to a runtime error
magazine = nil // Magazine Tech Today is deallocated

In this example, the unowned reference subscriber in the Magazine class assumes that the referenced subscriber will never be nil as long as the magazine instance exists.

Optional Unowned References

An optional unowned reference, on the other hand, is a variation of the unowned reference that can be nil. This is useful when you need an unowned reference, but there might be situations where the referenced object has already been deallocated. Accessing an optional unowned reference after the referenced object has been deallocated will not result in a crash; instead, it will simply return nil.

Let’s examine the usage of optional unowned references through an example:

class School {
    let name: String
    weak var principal: Person?
    
    init(name: String) {
        self.name = name
        print("School \(name) is initialized.")
    }
    
    deinit {
        print("School \(name) is deallocated.")
    }
}

class Person {
    let name: String
    var almaMater: School?
    
    init(name: String) {
        self.name = name
        print("Person \(name) is initialized.")
    }
    
    deinit {
        print("Person \(name) is deallocated.")
    }
}

var school: School?
var principal: Person?

school = School(name: "Swift High School")
principal = Person(name: "John")

school?.principal = principal
principal?.almaMater = school

principal = nil // Person John is deallocated
// Accessing school.principal now would return nil
school = nil // School Swift High School is deallocated

In this example, the optional unowned reference principal in the School class allows for the possibility that the referenced principal might already be deallocated.

Differences Between Unowned and Optional Unowned References

Here’s a summary of the key differences between unowned and optional unowned references:

Unowned References:
  • Assumes that the referenced object will never be nil.
  • Accessing an unowned reference after the referenced object is deallocated results in a runtime error.
  • Suitable when the referenced object’s existence is guaranteed.
Optional Unowned References:
  • Can be nil, accommodating situations where the referenced object might no longer exist.
  • Accessing an optional unowned reference after the referenced object is deallocated returns nil.
  • Useful when the referenced object’s existence is uncertain, and you want to handle the possibility of nil gracefully.

Conclusion

Understanding the differences between unowned and optional unowned references is crucial for effective memory management in Swift. Unowned references assume the referenced object’s existence during the lifetime of the reference, and accessing them after deallocation results in a runtime error. On the other hand, optional unowned references allow for nil values, accommodating situations where the referenced object might no longer exist. By choosing the appropriate reference type based on the certainty of the referenced object’s existence, developers can create memory-efficient Swift applications that handle object lifetimes gracefully. Happy coding!

Comments