I have tried to do a lot of research on understanding retain cycles. I can't seem to find anything on my examples though. I do know that if i set a property to a closure then a retain cycle happens and need to use weak or unowned. But i have 2 examples that I would like to know if they are done correctly: Thanks in advance, I have tried to see if they are on stackoverflow already but couldn't find anything.
Simple animations
UIView.transitionWithView(self, duration: 5, options: .TransitionCrossDissolve, animations: { [weak self] in
self?.setNeedsDisplay()
return
}, completion: nil)
Animations with an array
for imageView in self.townImages {
UIView.transitionWithView(imageView, duration: 0.3, options: .TransitionCrossDissolve, animations: { () -> Void in
imageView.image = UIImage(named: self.getImages()[count++])
}, completion: nil)
}
In both of these examples self
is a subclass of UIView
. I would just like to know that I am doing it correctly or if I should be using the imageView as weak reference too. Thanks.
Avoiding Retain Cycles In Closures In order for a closure to execute later, it needs to retain any variables that it needs for it to run. Similarly to classes, a closure captures references as strong by default. A retain cycle with a closure would look something like this: class SomeObject { var aClosure = { self.
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.
Neither of these will create retain cycles since the block is not attached to self
. Additionally, retain cycles with guaranteed life span aren't the worst thing in the world.
Let's consider some examples. (sorry, my swift isn't particularly strong, so I'm going to revert to obj-c.)
- (void)doSomething:(void(^)())block {
self.block = block;
}
// elsewhere
[self doSomething:^{
self.someProperty = 5;
}];
This creates a retain cycle because self
is referenced (not weakly) within a block to which self
holds a reference.
[UIView transitionWithView:self duration:5, options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
[self setNeedsDisplay];
} completion:nil];
This does not create a retain cycle because the animations
block is sent off to the system -- your UIView
subclass doesn't hold a reference to the block.
Side note: You shouldn't need to have a return
at the end of your closure, but I guess swift is ridiculous and tries to be "helpful". Also, I'm not sure you need to call self.setNeedsDisplay()
during the animation since it should be doing that itself...
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