I have a UIViewController
that has a reference to a Timer
object that is calling a closure repeatedly. The Timer
object captures self
in its block. As far as I understand this leads to a retains cycle
between the View Controller and the block. There is a logic to set the timer to nil and then the retain cycle is broken, but it may not be executed.
My question is the following: The View Controller will live as long as the app lives (at least in current implementation). In this case - how should I best take care of this retain cycle? Should I ignore it since the View controller won't be released anyway. Should I consider possible future changes and handle it with unowned
or weak
references and which one. I guess it should be unowned
since the timer is retained only by the View Controller and it should be released once the View Controller is released, but not sure if I am missing something. Thank you in advance. The following code is simple example of what I am talking about. Class A
is the View Controller.
class A {
var timer: Timer? = nil
var varToReference: Int = 0
func startTimer() {
timer = Timer.scheduledTimer(withTimeInterval: 2, repeats: true, block: { (theTimer) in
self.varToReference += 1
})
}
func stopTimer() {
if let theTimer = timer {
theTimer.invalidate()
timer = nil
}
}
func onAdapterStarts() {
self.startTimer()
}
func onAdapterStops(){
self.stopTimer()
}
deinit {
print("A Deinit")
}
}
Retain cycle is the condition when two objects keep a reference to each other and are retained, it creates a cycle since both objects try to retain each other.
In your example, Class A
owns the closure through the timer
variable. If you do not declare self
as weak
or unowned
the closure would also own self
creating a strong reference cycle.
unowned
and weak
A simple difference is between unowned
and weak
is that weak
is declared as optional where as unowned
is not. By declaring it weak
you get to handle the case that it might be nil inside the closure at some point. If you try to access an unowned
variable that happens to be nil, it will crash the whole program. So only use unowned
when you are positive that variable will always be around while the closure is around
Always be feature ready, as your work in any mobile app should always be expandable.