If you need to reference self
inside of a closure, it's good practice to pass it in as weak
or unowned
to prevent a retain cycle.
If I pass the function that belongs to self
directly, will it cause a retain cycle? Or does it need to be nested inside a closure to weakify self?
Passing directly
UIView.animateWithDuration(0.3,
delay: 0.0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.1,
options: .CurveEaseOut,
animations: self.view.layoutIfNeeded, // does this cause retain cycle?
completion: nil)
Wrapping in a closure
UIView.animateWithDuration(0.3,
delay: 0.0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.1,
options: .CurveEaseOut,
animations: { [unowned self] in
self.view.layoutIfNeeded()
},
completion: nil)
A strong reference cycle happens when 2 instances keep a strong reference to each other. You can accidentally create such a cyclic reference, for example when working with 2-way “links” between objects, or with closures. You can break the cycle by marking a reference as weak, or by setting one of the references to nil.
In Swift, [weak self] prevents closures from causing memory leaks in your application. This is because when you use [weak self], you tell the compiler to create a weak reference to self. In other words, the ARC can release self from memory when necessary.
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.
Use a weak reference whenever it is valid for that reference to become nil at some point during its lifetime. Conversely, use an unowned reference when you know that the reference will never be nil once it has been set during initialization. In general, be very careful when using unowned.
This should not create a reference cycle, but even if it did that would be ok. The reference cycle would only exist until the animation completed, at which point it would be broken. Creating short-lived reference cycles can actually be beneficial because it ensures that the target continues to exist for the life of the call. Cycles are not inherently a problem. Unbreakable cycles are the problem.
There are two reasons that this doesn't create a cycle. First, there is no "cycle." The system is going to reference something (more on that in a second), sure. But where's the reference to "the thing that is referencing that something?" To say it a bit more clearly, even if the animation system referenced self
, how is self
referencing the animation system? There is no cycle.
The other reason there is no cycle is that you're not passing self
to animation system anyway. Your passing self.view.layoutIfNeeded
. In Swift, that's equivalent to:
UIView.layoutIfNeeded(self.view)
You're not passing self
here. You're passing a view. Now the animation system almost certainly will hold a reference to that view until the animation completes, but that's fine. That's still not a cycle.
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