两种阻止保留周期的方法

时间:2016-06-15 02:32:00

标签: ios objective-c block retain-cycle

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

- (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:这是否意味着paramself运行处理程序时不会被释放?

1 个答案:

答案 0 :(得分:4)

在第二个示例中,在特定情况下创建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。它将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无法释放Request: PUT /products/:productId/coupons Body: { numberOfCoupons: 2 } }。