昨天我的最新iOS版本在Xcode上没有任何警告。在一夜之间升级到版本9.3(9E145)之后,我收到了多个警告。当我在answer (1)之后尝试self->score
类似问题时,警告就消失了。
但是在最近answer (2)相同的问题中,通过更改设置解决了问题。目前我Apple LLVM 9.0 - Warnings -Objective C and ARC
的设置是
在块内隐含保留'self'是
但是我不明白Block implicitly retains 'self'
在下面的代码的上下文中的含义,所以我不能说这个行为是否是“有意”的。或者我是解决了问题还是只是隐藏了它。或者答案1是否比答案2更好。
有人可以解释Block implicitly retains 'self'
在这种情况下的含义吗?感谢。
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];
答案 0 :(得分:13)
关于对self
的隐式引用的这个警告是有用的,因为在没有这个的情况下,当看到代码时,并不总是明显哪些块有引入强引用循环的风险,哪些不具有。通过鼓励程序员明确显示这些self
引用(例如安全编程语言(如Swift)中所需),您最终会得到代码,您可以清楚地看到强引用周期是否是潜在问题。 / p>
因此,我建议您启用警告,但继续使用self
显式隐式self->
引用(ivars),或者如果使用属性,{{1} },正如您引用的第一个答案所建议的那样。
然后,您可以查看self.
闭包的个别用法,并确保它们不会引入强参考周期的任何实际风险。如果他们这样做,您可以酌情采用self
或weakSelf
/ weakSelf
模式。
答案 1 :(得分:3)
假设:
- (void)bobIsYourUncle {
^{score.alpha = 0.0;}();
}
其中score
是一个实例变量,通过self
访问实例变量。由于块可能在某处被清除并稍后执行,因此块在创建块时会保留self
。
由于ivar通过self
访问无形解除引用,因此隐式保留在代码中并不明显。编译器在ivar前添加self->
的相当丑陋的建议使得至少显而易见的是self
被块捕获。
所以,是的,这是正确的行为。并且,是的,它有时是需要的。您可以通过在创建块之前(在局部变量中)抓取ivar的值来避免它,但您还必须知道这样做会更改获取ivar值的时间并且可能导致行为改变。