在块内访问BOOL

时间:2014-03-23 14:22:17

标签: ios objective-c objective-c-blocks

我正在尝试使用块内的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,并且很好地解决了这一切,但我的好奇心促使我不要对它视而不见。

2 个答案:

答案 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
});

总结一下:为了确保在使用对象时不会取消分配对象,您应该获得对它的强引用。另一方面,为了防止内存泄漏,您应该使用弱引用。算法如下所示:

  1. 获得对感兴趣对象的弱引用
  2. schedule block
  3. 在块开始时获得强大的参考
    1. 如果对象仍然存在 - 做你需要的任何事情
    2. 如果先前已取消分配对象 - 跳过块
    3. 中的操作

  4. iVar只是编译器在编译时为类创建的C结构的成员。所有对ivars的引用都将编译为self-><ivar_name>

    您可以参考Apple's docs了解详情或LLVM specs on ARCLLVM 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时,它不会在一个纳秒之后。