在Objective-C中,在块内为弱者分配弱点意味着什么?

时间:2013-12-16 17:20:27

标签: objective-c automatic-ref-counting objective-c-blocks

在Objective-C中,将weak分配给块中的strong是什么意思?现场背后发生了什么?

e.g。

__weak __typeof(self) wself = self;

void (^cmd)() = ^(){
    __strong __typeof(self) sself = wself;
    if (!sself) return;
    ...
};

2 个答案:

答案 0 :(得分:9)

这里的意图有两个方面:

  1. 首先,是使用:

    __weak __typeof(self) wself = self;
    

    这可确保cmd块不会保留对self的强引用。这确保了,如果cmd是类的实例变量,那么您最终不会得到强引用循环。如果不使用此wself模式,那么将cmd作为实例变量的类永远不会被释放,并且您将泄漏具有cmd的对象作为实例变量。

    有关详细信息,请参阅使用Objective-C编程:使用块文档的Avoid Strong Reference Cycles when Capturing self部分。

  2. 其次,在块内使用以下内容:

    __strong __typeof(self) sself = wself;
    if (!sself) return;
    

    这确保了,如果块开始执行,如果wself已经被释放,则该块将退出。但是,如果尚未释放wself,则通过分配sself,您确保在执行块期间将保留该对象。

    此外,如果您引用块中的任何ivars,请注意您要取消引用它们(因为否则块中存在对self的隐式引用,可能导致该强引用循环)。但是你不能使用弱指针取消引用ivars(例如不允许使用wself->someIvar),但你可以使用这个本地强指针(例如sself->someIvar)。一般来说,你不应该取消引用ivars,而是使用属性,但是使用本地强引用self是另一个原因。

  3. 通常,您会看到此构造与类属性(或ivar)结合使用:

    @property (nonatomic, copy) void (^commandBlock)(void);
    

    而且,作为惯例,您通常会看到更多描述性变量名称weakSelfstrongSelf,因此:

    __weak __typeof(self) weakSelf = self;
    
    self.commandBlock = ^(){
        __strong __typeof(self) strongSelf = weakSelf;
        if (!strongSelf) return;
        ...
    };
    

    当您拥有自己的类属性并且希望(a)阻止强引用周期(也称为保留周期)时,此weakSelf / strongSelf模式非常常见;但是(b)希望确保在执行块的过程中不能释放有问题的对象。

答案 1 :(得分:5)

如果您没有为weak分配strong引用,则weak引用引用的对象可以在块执行过程中释放 - 这可能是您不期望的。如果分配给strong,只要强引用在范围内,该对象就会被保留(除非该对象在分配之前已经被释放)。

当您为强编译器分配弱引用时,将Objective-C运行时函数调用插入到代码中,该代码根据需要递增对象引用计数器以保留它。当强变量超出范围时(或更早,在最后一次使用强变量之后),编译器插入的另一个调用会减少引用计数器。