0
0
Swiftprogramming~20 mins

Strong reference cycles between classes in Swift - Practice Problems & Coding Challenges

Choose your learning style9 modes available
Challenge - 5 Problems
🎖️
Strong Reference Cycle Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
Predict Output
intermediate
2:00remaining
Output of code with strong reference cycle
What will be printed when this Swift code runs?
Swift
class Person {
    let name: String
    var apartment: Apartment?
    init(name: String) {
        self.name = name
        print("Person \(name) is initialized")
    }
    deinit {
        print("Person \(name) is being deinitialized")
    }
}

class Apartment {
    let unit: String
    var tenant: Person?
    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) is initialized")
    }
    deinit {
        print("Apartment \(unit) is being deinitialized")
    }
}

var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john

john = nil
unit4A = nil
A
Person John Appleseed is initialized
Apartment 4A is initialized
Person John Appleseed is being deinitialized
B
Person John Appleseed is initialized
Apartment 4A is initialized
Person John Appleseed is being deinitialized
Apartment 4A is being deinitialized
C
Person John Appleseed is initialized
Apartment 4A is initialized
DNo output, program crashes
Attempts:
2 left
💡 Hint
Think about what happens when two objects hold strong references to each other.
Predict Output
intermediate
2:00remaining
Breaking strong reference cycle with weak reference
What will be printed when this Swift code runs?
Swift
class Person {
    let name: String
    var apartment: Apartment?
    init(name: String) {
        self.name = name
        print("Person \(name) is initialized")
    }
    deinit {
        print("Person \(name) is being deinitialized")
    }
}

class Apartment {
    let unit: String
    weak var tenant: Person?
    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) is initialized")
    }
    deinit {
        print("Apartment \(unit) is being deinitialized")
    }
}

var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john

john = nil
unit4A = nil
A
Person John Appleseed is initialized
Apartment 4A is initialized
Person John Appleseed is being deinitialized
Apartment 4A is being deinitialized
B
Person John Appleseed is initialized
Apartment 4A is initialized
C
Person John Appleseed is initialized
Apartment 4A is initialized
Apartment 4A is being deinitialized
D
Person John Appleseed is being deinitialized
Apartment 4A is being deinitialized
Attempts:
2 left
💡 Hint
Look at the keyword used for the tenant property.
🔧 Debug
advanced
2:00remaining
Identify the cause of memory leak
Why does this Swift code cause a memory leak?
Swift
class Customer {
    let name: String
    var card: CreditCard?
    init(name: String) {
        self.name = name
    }
    deinit {
        print("Customer \(name) is being deinitialized")
    }
}

class CreditCard {
    let number: UInt64
    var customer: Customer?
    init(number: UInt64) {
        self.number = number
    }
    deinit {
        print("CreditCard \(number) is being deinitialized")
    }
}

var alice: Customer? = Customer(name: "Alice")
var card: CreditCard? = CreditCard(number: 1234_5678_9012_3456)
alice!.card = card
card!.customer = alice

alice = nil
card = nil
ABecause the CreditCard number is too large and causes overflow.
BBecause both Customer and CreditCard hold strong references to each other, causing a strong reference cycle.
CBecause the Customer class does not implement deinit properly.
DBecause the variables alice and card are declared as optional.
Attempts:
2 left
💡 Hint
Check how the references between Customer and CreditCard are declared.
Predict Output
advanced
2:00remaining
Output with unowned reference to break cycle
What will be printed when this Swift code runs?
Swift
class Customer {
    let name: String
    var card: CreditCard?
    init(name: String) {
        self.name = name
        print("Customer \(name) is initialized")
    }
    deinit {
        print("Customer \(name) is being deinitialized")
    }
}

class CreditCard {
    let number: UInt64
    unowned let customer: Customer
    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
        print("CreditCard \(number) is initialized")
    }
    deinit {
        print("CreditCard \(number) is being deinitialized")
    }
}

var alice: Customer? = Customer(name: "Alice")
alice!.card = CreditCard(number: 1234_5678_9012_3456, customer: alice!)
alice = nil
A
Customer Alice is initialized
CreditCard 1234567890123456 is initialized
Customer Alice is being deinitialized
CreditCard 1234567890123456 is being deinitialized
B
Customer Alice is initialized
CreditCard 1234567890123456 is initialized
Customer Alice is being deinitialized
C
Customer Alice is initialized
CreditCard 1234567890123456 is initialized
CreditCard 1234567890123456 is being deinitialized
DRuntime error due to unowned reference being nil
Attempts:
2 left
💡 Hint
Unowned references do not increase reference count but assume the referenced object exists.
🧠 Conceptual
expert
2:00remaining
Choosing between weak and unowned references
Which statement best describes when to use weak versus unowned references in Swift to avoid strong reference cycles?
AUse weak when the reference is optional; use unowned when the reference is always nil.
BUse weak only for classes and unowned only for structs.
CUse unowned when you want the reference to increase the reference count; use weak when you want to decrease it.
DUse weak when the reference can become nil during its lifetime; use unowned when the reference is expected to always have a value after initialization.
Attempts:
2 left
💡 Hint
Think about whether the reference might become nil or not during the object's lifetime.