原始属性的 ivars 有什么数据类型?

What data type do ivars for primitive properties have?

我问是因为我正在研究一些复杂的块代码,我没想到下面的代码可以正常工作。

假设我们有一个 BOOL 属性,这样:

@property (nonatomic, assign) BOOL isCancelled;

它是自动合成的,没有自定义 getter,没有 setter,没有明确的 ivar。

然后,就是这段代码...完美运行

dispatch_async(queue, ^{
    id result = block(&_isCancelled);
    if (!_isCancelled) { ... }
}

但是,我希望它适用于 block() 调用,但不适用于 if,我认为它会捕获 _isCancelled 的值并保持常量,而不是让它在整个执行过程中发生变化。尽管如此,在运行时,_isCancelled 的值始终与块一致 inside/outside,就好像它实际上是 BOOL *

谁能解释一下这是怎么回事?

TL;DR: 与 属性.

类型相同

所有对象指针和基本类型都是标量值 - 即奇异值。它们都需要存储在内存中的一个地址,因此它们都有自己的内存地址。

通过传递 &_isCancelled,您传递的是 BOOL 变量的 地址 ,所以block() 已经是 "let in on a secret" - 即 BOOL 的位置 - 所以它可以更新它。然后,您将检查 _isConnected 的结果 actual 值。这适用于原始类型(标量)和对象指针(也是标量)。

是否属性无关紧要。

当声明 属性 BOOL cancelled 时,自动合成的 ivarBOOL _isCancelled。这是原始变量,不是指针。

然而,当一个块正在捕获 ivar 时,它实际上是在捕获 self,而不是 ivar 本身。读ivar _isCancelled其实就是读self->_isCancelled.

因此,ivar 不会按值捕获,除非您先将它们保存到局部变量中(例如 BOOL isCancelled = _isCancelled)。

有关详细信息,请参阅 Block automatic retaining, does it affect even to ivars in self?