Delegate Retention Cycle
Introduction
Welcome to Lesson 2 of Swift Memory Management. You will discover a potential retain cycle that might occur while using the delegate pattern.
Problem
Why delegate should be weak var
Design Delegate Pattern
Let us create a classic structure: the protocol, the delegator, and the delegate.
Design Protocol
protocol SendDataDelegate {}
Design Sender/Delegator
class SendingVC {
var delegate: SendDataDelegate?
deinit {
print("Delegator gone")
}
}
Design Receiver/Delegate
class ReceivingVC: SendDataDelegate {
lazy var sendingVC: SendingVC = {
let vc = SendingVC()
vc.delegate = self
return vc
}()
deinit {
print("Delegate gone")
}
}
Important: The closure init method is used with the
lazy
keyword from 3003_lazy_init_closures. You may not interact withself
while creating a brand new property since it is not initialized. However,lazy
allows since the property is initialized only afterself
has been created.
Create Instances
var receivingVC: ReceivingVC? = ReceivingVC()
receivingVC?.sendingVC // lazy born
Let us visualize the relationship.
There is a retain cycle. Even if you set recevingVC
as nil
, there is a reference count for both ReceivingVC
and SendingVC
from each other.
receivingVC = nil
// not deallocated
Deallocate
Make one of the relationships/references as weak
.
class SendingVC {
weak var delegate: SendDataDelegate?
...
}
However, as soon as you work with weak
which only applies to reference types, the compiler forces you to indicate the protocol as a different animal
protocol SendDataDelegate: class {}
Let us visualize the relationship.
Let us deallocate
receivingVC = nil
// "Delegate gone"
Notice that the SendingVC
object also has been deallocated since it no longer has a reference from the ReceivingVC
object.
Rules
- A
weak
reference allows the referencing object to becomingnil
(this happens automatically when the referenced object is deallocated) - Based on the rule above, the referencing object/variable must be
optional
Source Code
5002_delegate_retention_cycle.playground
Conclusion
You’ve learned how to spot a retain cycle within the delegate pattern. You may wonder which variable should be set as weak
. The #1 rule is, a weak
property has a reference to a class object which more likely to stays longer, and eventually has greater importance. For example, if the SendingVC
object has a weak reference from the recevingVC
property, the object will be deallocated immediately since the reference count is zero.
In the following lesson, you will discover the pitfall of using closures due to the unique behavior you’ve learned in Chapter 3, 3004_capture_lists
Note: Learn Swift with Bob is available on Udemy. If you wish to receive a discount link, you may sign up here.