可以在没有__weak对象(iOS 5 + ARC)的情况下通过
是否可以传递[self的任何function]块没有__weak对象从自我?
作为一个例子,这是来自System Framework的有效代码:
[UIView animateWithDuration:0.8 animations:^{ //Do animationStuff } completion:^(BOOL finished) { [self anyFunction]; }];
您可以在完成块中传递[self anyFunction]
而不发出警告。 但是,如果您使用完成块编写自己的方法,则会发生以下警告: 在此块中强烈捕获“自我”可能会导致保留周期 。
一个可行的解决scheme非常简单(iOS 5 + ARC)。 在块声明之前:
__weak MyClass *weakSelf = self;
并在完成块,你必须打电话:
[weakSelf anyFunction];
但是,回到我的问题:为什么没有必要在系统框架API中使用__weak
对象,并使用self
没有任何警告。 以及如何在块中实现一个方法,而不需要__weak
对象?
感谢你的付出。
抛出错误的块是捕获拥有块的对象的块。 例如
[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
引用被块保留,但是没有循环,因为自身没有保留块。
以同样的方式,你可能已经注意到,并不是所有在块中使用的对象都需要弱引用 – 就是那些引起保留周期的对象。
在需要使用或不使用ARC进行编译的代码上,或者使用或不使用较新的编译器时,我会执行以下…function上与已经列出的function相同,但它避免了_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; }];