我在问,因为我正在涉及一些复杂的块代码,我不希望以下代码正常工作。
假设我们有一个BOOL属性,如下:
@property (nonatomic, assign) BOOL isCancelled;
它是自动合成的,没有自定义的吸气剂,没有固定器,也没有明确的静脉注射器。
然后,这段代码......完美无缺
dispatch_async(queue, ^{
id result = block(&_isCancelled);
if (!_isCancelled) { ... }
}
但是,我本来期望它适用于block()调用,但不适用于if,我认为它会捕获_isCancelled的值并保持const,而不是在整个执行过程中进行变异。仍然,在运行时,_isCancelled的值在块内/外总是一致的,就好像它实际上是BOOL *
有谁可以解释发生了什么?
答案 0 :(得分:0)
TL; DR:与属性相同的类型。
所有对象指针和基元类型都是标量值 - 即奇异值。它们都需要存储在内存中的地址中,因此它们都有自己的内存地址。
通过& _isCancelled
,您传递BOOL
变量的地址,因此block()
已被“放进秘密” - 即BOOL
的位置 - 所以它可以更新它。然后,您将检查_isConnected
的结果实际值。这适用于原始类型(标量)和对象指针(也是标量)。
它的财产是否无关紧要。
答案 1 :(得分:0)
声明属性BOOL cancelled
时,自动合成的 ivar 为BOOL _isCancelled
。这是一个原始变量,而不是指针。
然而,当一个块正在捕获ivars时,它实际上是捕获self
,而不是ivar本身。阅读ivar _isCancelled
实际上意味着阅读self->_isCancelled
。
因此,除非您先将它们保存到局部变量(例如BOOL isCancelled = _isCancelled
),否则不会按值捕获ivars。
有关详细信息,请参阅Block automatic retaining, does it affect even to ivars in self?。