I’m working in a pure iOS5/ARC environment, so I can use __weak references as needed. I do reference ivars in a block in many situations, most notably, animation blocks that move views around, which are properties of say, my view controller class.
My question:
In the most trivial use of ivars in a block, am I creating a reference cycle? Do I need to use the __weak self / strong self technique everytime I write a block that manipulates instance variables of the containing object?
I’ve been re-watching the 2011 WWDC Session #322 (Objective-C Advancements in Depth) to understand the nuances regarding the 3 minute segment starting at time index 25:03 about “Reference Cycle Via Captured Self”. To me, this implies any usage of ivars in a block should be safeguarded with the weak self / strong self setup as described in that segment.
The sample method below on a view controller, is typical of animations I do.
In the openIris block, is it wrong to reference ivars “_topView” and “_bottomView” as I have?
Should I always setup a __weak reference to self before the block, then a strong reference inside the block to the weak reference just setup prior, and then access the ivars through that strong reference within my block?
From the WWDC session, I understand that referencing ivars in a block is really creating a reference to the implied self that these ivars hang off of.
To me, this implies that there really isn’t any simple or trivial case where it is correct to access ivars in a block without the weak/strong dance to ensure no cycles. Or am I reading to much into a corner case that doesn’t apply to simple cases, such as my example?
- (void)openIrisAnimated:(BOOL)animated
{
if (_isIrisOpened) {
NSLog(@"Asked to open an already open iris.");
return; // Bail
}
// Put the common work into a block.
// Note: “_topView” and “_bottomView” are the backing ivars of
// properties “topView” and “bottomView”
void (^openIris)() = ^{
_topView.frame = CGRectMake(....);
_bottomView.frame = CGRectMake(....);
};
// Now do the actual opening of the iris, whether animated or not:
if (animated) {
[UIView animateWithDuration:0.70f
animations:^{
openIris();
}];
}
else {
openIris();
}
_irisOpened = YES; // Because we have now just opened it
}
Here’s how I’d re-write the openIris block piece using the guidance from Session #322, but I’m just wondering if all my similar blocks require this weak/strong reference dance to ensure correctness and stability:
__weak MyClass *weakSelf = self;
void (^openIris)() = ^{
MyClass *strongSelf = weakSelf;
if (strongSelf) {
strongSelf.topView.frame = CGRectMake(....);
strongSelf.bottomView.frame = CGRectMake(....);
}
};
Is this in fact, necessary?