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

Boo*_*oon 5 objective-c objective-c-blocks automatic-ref-counting

在Objective-C,这是什么意思,以分配weakstrong一个块中?现场背后发生了什么?

例如

__weak __typeof(self) wself = self;

void (^cmd)() = ^(){
    __strong __typeof(self) sself = wself;
    if (!sself) return;
    ...
};
Run Code Online (Sandbox Code Playgroud)

Rob*_*Rob 9

这里的意图有两个方面:

  1. 一,是使用:

    __weak __typeof(self) wself = self;
    
    Run Code Online (Sandbox Code Playgroud)

    这可以确保cmd块不会保持强引用self.这确保了,如果cmd是类的实例变量,那么您最终没有强大的引用循环.如果不使用此wself模式,则cmd永远不会释放具有实例变量的类,并且您将泄漏具有cmd实例变量的对象.

    有关更多信息,请参阅使用Objective-C:使用块编程文档中的" 捕获自我时避免强引用循环"部分.

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

    __strong __typeof(self) sself = wself;
    if (!sself) return;
    
    Run Code Online (Sandbox Code Playgroud)

    这确保了,如果块开始执行,如果wself已经解除分配,则块将退出.但是如果wself尚未解除分配,则通过分配sself,确保在执行块期间保留对象.

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

通常,您会看到此构造与类属性(或ivar)一起使用:

@property (nonatomic, copy) void (^commandBlock)(void);
Run Code Online (Sandbox Code Playgroud)

而且,由于习惯问题,你通常看到更具描述性的变量名,weakSelf并且strongSelf,这样的:

__weak __typeof(self) weakSelf = self;

self.commandBlock = ^(){
    __strong __typeof(self) strongSelf = weakSelf;
    if (!strongSelf) return;
    ...
};
Run Code Online (Sandbox Code Playgroud)

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


yur*_*ish 5

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

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