Challenge - 5 Problems
Strong Reference Cycle Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate2: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
Attempts:
2 left
💡 Hint
Think about what happens when two objects hold strong references to each other.
✗ Incorrect
Because Person and Apartment hold strong references to each other, neither is deinitialized when john and unit4A are set to nil. This causes a strong reference cycle, so the deinit methods are not called.
❓ Predict Output
intermediate2: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
Attempts:
2 left
💡 Hint
Look at the keyword used for the tenant property.
✗ Incorrect
Using weak for tenant breaks the strong reference cycle. When john and unit4A are set to nil, both objects are deinitialized and their deinit messages print.
🔧 Debug
advanced2: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
Attempts:
2 left
💡 Hint
Check how the references between Customer and CreditCard are declared.
✗ Incorrect
Both Customer and CreditCard hold strong references to each other through their properties. This creates a strong reference cycle, preventing deinitialization and causing a memory leak.
❓ Predict Output
advanced2: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
Attempts:
2 left
💡 Hint
Unowned references do not increase reference count but assume the referenced object exists.
✗ Incorrect
Using unowned for customer breaks the strong reference cycle. When alice is set to nil, both Customer and CreditCard are deinitialized and their messages print.
🧠 Conceptual
expert2: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?
Attempts:
2 left
💡 Hint
Think about whether the reference might become nil or not during the object's lifetime.
✗ Incorrect
Weak references are optional and can become nil, so they are used when the referenced object might be deallocated first. Unowned references are non-optional and used when the referenced object is expected to always exist during the lifetime of the referencing object.