Yesterday my latest iOS build ran free of warnings on Xcode. Following an upgrade to Version 9.3 (9E145) overnight I got multiple warnings. When I tried self->score
following an answer (1) to a similar question the warnings disappeared.
But in a more recent answer (2) to the same question the problem is solved by altering settings. Currently my settings for Apple LLVM 9.0 - Warnings -Objective C and ARC
are
Implicit retain of ‘self’ within blocks Yes
But I don’t understand what Block implicitly retains 'self'
means in the context of the code below so I can't say whether or not this behaviour is ‘intended’. Or whether I solved a problem or simply hid it. Or whether answer 1 would be better than answer 2.
Could someone kindly explain what Block implicitly retains 'self'
means in this context ? Thanks.
score.alpha = 1.0;
if (sequenceState >= STATES_Count)
{
[GraphicScore animateWithDuration:8.0f
delay:1.0f
options:UIViewAnimationOptionCurveEaseOut
animations:^{self->score.alpha = 0.0;} // animations:^{score.alpha = 0.0;}
completion:^(BOOL finished){ }];
}
[self addSubview:score];
This warning about implicit references to self
is useful because in the absence of that, when glancing at code it isn't always obvious which blocks have the risk of introducing strong reference cycles and which don't. By encouraging the programmer to make these self
references explicit (such as is required in safe programming languages like Swift), you end up with code where you can plainly see whether a strong reference cycle is a potential issue or not.
So, I'd encourage you to leave the warning turned on but go ahead and make those implicit self
references (the ivars) explicit with self->
or, if using properties, self.
, as advised by the first answer you referenced.
Then you can review those individual uses of self
closures and make sure they don't introduce any real risk of strong reference cycles. And if they do, you can adopt the weakSelf
or weakSelf
/strongSelf
patterns as appropriate.
Given:
- (void)bobIsYourUncle {
^{score.alpha = 0.0;}();
}
Where score
is an instance variable that instance variable is accessed via self
. Because the block may be equeued somewhere and executed later, the block retains self
when the block is created.
Because ivar access invisibly dereferences through self
, that implicit retain is kinda not apparent in the code. The rather ugly suggestion by the compiler of adding self->
in front of the ivar makes it, at least, obvious that self
is captured by the block.
So, yes, it is the correct behavior. And, yes, it is sometime desired. You could avoid it by grabbing the ivar's value before the block is created (in a local variable), but you must also know that doing so changes the time at which the ivar's value is obtained and that could cause a behavior change.
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