I have a UIViewController
and in it a UIToolbar
. They get instantiated from a storyboard.
I made a custom class for my UIToolbar
. Based on some logic I do or do not show buttons on it.
The UIViewController
needs to take action when some of the buttons are tapped.
For this I created a delegate protocol in the UIToolbar
.
Currently, when I dismiss the view, it is kept in memory. Further investigation revealed my delegate created a retain cycle.
In Objective-C, we would simply define delegates as weak
. However, I am using Swift, and it does not allow me to define delegate
variable as weak
:
weak var navigationDelegate: MainToolBarDelegate?
// 'weak' cannot be applied to non-class type 'MainToolBarDelegate'
When I dismiss the view controller, I set self.toolBar.navigationDelegate = nil
and the memory gets cleared. But it feels wrong!
Why do I get the retain cycle and why can I not simply define the delegate as weak
?
Retain cycles: This is the state when two objects hold weak references to one another. Since the first object's reference count cannot be 0 until the second object is released, and the second object's reference count cannot be 0 until the first objet is released neither object can be released!
In order to prevent this retain cycle, we need to declare at least one of the variable as weak or unowned. We can break the retain cycle with adding a weak keyword before either the driver property of the Car class or the car property of the Person class.
Structs and Classes A choice between a struct and a class can cause a retain cycle. Both structs and classes can have constants, variables, functions and protocols.
Avoiding retain cycles rule #1: An object must never retain its parent. The first rule to avoid retain cycles is that an object must never retain its parent. This changes the previous diagram to the following: This is the easy case: an object should never retain its parent when it makes a pointer to the parent.
weak
references only apply to classes, not structs or enums, which are value types. But protocols by default can apply to any of those types.
Define your MainToolBarDelegate
as a class-only protocol:
protocol MainToolBarDelegate: class {
}
Then you'll be able to declare your delegate as weak
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With