原始属性的 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
时,自动合成的 ivar 是 BOOL _isCancelled
。这是原始变量,不是指针。
然而,当一个块正在捕获 ivar 时,它实际上是在捕获 self
,而不是 ivar 本身。读ivar _isCancelled
其实就是读self->_isCancelled
.
因此,ivar 不会按值捕获,除非您先将它们保存到局部变量中(例如 BOOL isCancelled = _isCancelled
)。
有关详细信息,请参阅 Block automatic retaining, does it affect even to ivars in self?。
我问是因为我正在研究一些复杂的块代码,我没想到下面的代码可以正常工作。
假设我们有一个 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
时,自动合成的 ivar 是 BOOL _isCancelled
。这是原始变量,不是指针。
然而,当一个块正在捕获 ivar 时,它实际上是在捕获 self
,而不是 ivar 本身。读ivar _isCancelled
其实就是读self->_isCancelled
.
因此,ivar 不会按值捕获,除非您先将它们保存到局部变量中(例如 BOOL isCancelled = _isCancelled
)。
有关详细信息,请参阅 Block automatic retaining, does it affect even to ivars in self?。