如果可能存在保留周期,我通常使用这样的块:

- (void)someFunction {
    __weak __typeof(self) weakSelf = self;
    [self setHandler:^{
        [weakSelf doSomething];
    }];
}

但是最近我看到了另一种方式:
- (void)someFunctionWithParam:(id)param {
    __weak __typeof(param) weakParam = param;
    [self setHandler:^{
        __typeof(weakParam) strongParam = weakParam;
        [strongParam doSomething];
    }];
}

它们之间有什么区别?

Edit1:这是否意味着在运行处理程序的param时不会释放self

最佳答案

在第二个示例中,在这种特定情况下创建strongSelf变量没有任何好处,但是我可以向您展示一个有好处的示例。

在第一个示例中,语句[weakSelf doSomething]将引用加载到weakSelf中,保留该引用,发送doSomething消息,然后(在doSomething返回之后)释放该引用。第二个示例“手动”执行了完全相同的步骤。

这是一个稍微不同的示例:

- (void)someFunction {
    __weak __typeof(self) weakSelf = self;
    [self setHandler:^{
        [weakSelf doSomething];
        [weakSelf doAnotherThing];
    }];
}

在我的代码中,假设在调用该块时只有一个对self对象的强引用。 [weakSelf doSomething]语句创建第二个临时强引用。当doSomething运行时,另一个线程释放另一个强引用。当doSomething返回时,该语句释放其临时强引用。现在self不再具有更强的引用,因此将其释放,并将weakSelf设置为nil。

然后[weakSelf doAnotherThing]语句运行。它想加载和保留weakSelf的内容,但是由于weakSelf现在为nil,因此该语句仅使用nil。它将doAnotherThing消息发送到nil,这是允许的,并且不会崩溃。它什么也没做。它不调用方法。

这可能不是您想要的行为。也许您总是,如果doAnotherThing运行,则希望selfdoSomething上运行。那是您在第二个示例中需要该模式时:
- (void)someFunctionWithParam:(id)param {
    __weak __typeof(self) weakSelf = self;
    [self setHandler:^{
        __typeof(weakSelf) strongSelf = weakSelf;
        [strongSelf doSomething];
        [strongSelf doAnotherThing];
    }];
}

在这里,当调用该块时,它立即在self中存储对strongSelf的强引用(或者,如果weakSelf已经设置为nil,则存储nil)。直到最后一次使用strongSelf变量后,才能释放strongSelf参考,因此,不可能将self释放在doSomething之后但在doAnotherThing之前。

关于ios - 防止滞留周期的两种挡块方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37825148/

10-14 03:52