是否可以在没有__weak对象的块中传递[self anyFunction]?
作为示例,这是来自系统框架的有效代码:
[UIView animateWithDuration:0.8 animations:^{
//Do animationStuff
} completion:^(BOOL finished) {
[self anyFunction];
}];
您可以在完成块中传递[self anyFunction]
而不会发出警告。但如果您使用完成块编写自己的方法,则会出现以下警告:在此块中强烈捕获“自我”可能会导致保留周期。
工作解决方案非常简单(iOS 5 + ARC)。在块声明之前:
__weak MyClass *weakSelf = self;
在完成程序段中,您必须致电:
[weakSelf anyFunction];
但是,回到我的问题:为什么系统框架API中不需要使用__weak
对象并在没有任何警告的情况下使用self
。以及如何在块中不需要__weak
对象的情况下实现方法?
感谢您的努力。
答案 0 :(得分:53)
抛出错误的块是捕获拥有块的对象的块。例如
[object performBlock:^{
[object performSomeAction]; // Will raise a warning
}];
或
[self performBlock:^{
[self doSomething]; // Will raise a warning
}];
但
[self performBlock:^{
[object doSomething]; // <-- No problem here
}];
因为一个对象保留了它的块,一个块保留了它的对象。因此,在这两种情况下,执行块的对象拥有块,该块也拥有该对象。所以你有一个循环 - 一个保留周期。这意味着内存泄露。
在您给出的示例中 - 您正在查看类方法。您在UIView
类上调用块,而不是UIView
对象。类没有与之关联的内存。你可能正在从一个控制器调用这个函数,所以块保留self
引用,但没有循环,因为self没有保留块。
就像你可能注意到的那样,并非所有在块中使用的对象都需要被弱引用 - 只是导致保留周期的对象。
答案 1 :(得分:14)
对于我需要使用或不使用ARC进行编译的代码,或者有或没有更新的编译器,我执行以下操作...功能上它与您已经列出的相同,但它避免了_weak并且也避免了保留释放周期:
//
// FOR NON-ARC PROJECTS
//
__block __typeof__(self) bself = self;
[someObject doThingWithBlock:^(id result){
if (!bself)
return;
bself.thingWhich = result;
}];
///
// FOR ARC PROJECTS
//
__weak MyClass *bself = self;
[someObject doThingWithBlock:^(id result){
if (!bself)
return;
bself.thingWhich = result;
}];