我正在尝试使用块内的BOOL
设置标记。
我声明BOOL
是这样的:
@property(nonatomic) BOOL flag;
在街区内:
__strong typeof(self) strongSelf = weakSelf;
if(strongSelf->_flag)
我的问题是,如果我这样做:
__weak typeof(self) weakSelf = self;
if(weakSelf->_flag)
我会收到错误:
"取消引用__weak指针不允许死为可能的null 由竞争条件引起的价值,首先将其分配给强变量"
有人可以向我解释这意味着什么吗?
此外,我觉得有趣的是我必须使用BOOL
来引用__strong
(即strongSelf->_flag
),是否与使用self->_flag
相同,因为我会在这里使用强大的自我?
更重要的是,如果我将BOOL
声明为ivar而不是属性:
BOOL flag;
当我在街区内使用它时,它会给我一个警告:
if(flag)
所以我还需要做以下事情:
__strong typeof(self) strongSelf = weakSelf;
if(strongSelf->flag)
这让我感到困惑,因为通常情况下我们引用的是没有self
的ivar,只有flag
,但上面的情况在我看来它正在访问像self->_flag
这样的ivar。
...
我可以使用其他东西,比如NSNumber
,并且很好地解决了这一切,但我的好奇心促使我不要对它视而不见。
答案 0 :(得分:4)
我假设您在某个操作队列中安排块操作,或者在将来稍后执行该块时。
您不应将self
分配给块内的weakSelf
。你应该在块外面这样做
__weak typeof(self) weakSelf = self;
if(weakSelf->_flag)
__ weak指定不使引用对象保持活动状态的引用。当没有对象的强引用时,弱引用设置为nil。 Apple arc docs
你实际上希望你的weakSelf
不能为空做一些事情。为此,您必须声明将其分配给具有强所有权限定符的变量。
草图:
__weak id weakSelf = self;
schedule_block(^{
// at this point the object pointed by weakSelf may or may not be deallocated
id strongSelf = self; // after this point the object referenced by `strongSelf` will not be deallocated at least `strongSelf` to the end of current block
//You may safely work with `strongSelf` and be sure the object will live at least to the end of current block
});
总结一下:为了确保在使用对象时不会取消分配对象,您应该获得对它的强引用。另一方面,为了防止内存泄漏,您应该使用弱引用。算法如下所示:
iVar只是编译器在编译时为类创建的C结构的成员。所有对ivars的引用都将编译为self-><ivar_name>
。
您可以参考Apple's docs了解详情或LLVM specs on ARC或LLVM specs on blocks
答案 1 :(得分:1)
从一个指向对象的弱指针开始。对象可以随时消失,将弱指针设置为nil。一旦你将它指定给一个强指针,如果当时弱指针为零,则强指针可能已被设置为nil,但是一旦设置为非零,它就会保持非零,因为它保持一个引用保持对象活着。
if (strongSelf->_flag)
是危险的,因为strongSelf可能是零,导致崩溃。
if (strongSelf != nil && strongSelf->_flag)
是安全的,因为除非strongSelf不是nil,否则不会测试该标志。
if (weakSelf->_flag)
显然也很危险。但也许令人惊讶的是
if (weakSelf != nil && weakSelf->_flag)
也很危险,因为当你检查它时,weakSelf不是nil,并不意味着当你试图访问_flag时,它不会在一个纳秒之后。