[英]What is the correct way to be sure that the object will be there and it won't leak while using blocks with ARC on iOS?
以下哪个代码段是正确的?
“我”的正确定义:
更新:(其他信息)仪器工具确实显示出奇怪的泄漏,直到我将__block替换为__weak为止。 但是,此后,我记得__weak引用可能随时消失。 我必须确保它也不会消失和泄漏。 我没有计时器。 当它观察到特定的NSNotification时,在主线程上调用此someMethod。
@implementation MyObject...
-(void)someMethod{
AnotherObject *abc=[[AnotherObject alloc]init];
__weak MyObject *weakSelf=self;
abc.onSuccess=^{
__strong MyObject * strongSelf = weakSelf;
[strongSelf method2];
[strongSelf method3];
}
}
要么
@implementation MyObject...
-(void)someMethod{
AnotherObject *abc=[[AnotherObject alloc]init];
__block MyObject *blockSelf=self;
abc.onSuccess=^{
[blockSelf method2];
[blockSelf method3];
blockSelf=nil;
}
}
更新2:实际代码,如果我不使用__weak总是会泄漏:
__block RButton *_self=self;
_aimageView.onSuccess=^(void){
[_self.headerLabel setText:[_self.book title]];
_self = nil;
};
我已经在“更新2”中查看了您的实际代码,但是缺少很多信息。 例如, _aimageView
是实例变量吗? 局部变量? 要不然是啥? 是什么导致此onSuccess
被调用?
如果_aimageView
是局部变量,那么我看不到保留周期的证据。
我的第一个想法是我不明白为什么要保证在此示例中运行块体内的代码。 看起来其中的代码只是在更新一些UI元素。 好吧,如果UI不再显示(例如,当前对象可能没有通过此块对其进行引用),那么更新UI元素的意义何在?
重要的是要知道是什么导致了onSuccess
调用,因为不同类型的回调需要不同的内存管理架构。 例如,如果响应某个触摸或类似事件触发了该块,则可能是self
指向的对象(可能是某种视图或视图控制器)必须仍然存在,以便事件发生。 如果真是这样,那么__weak
会做您想要的。
基本上,通过命名这些变量,可以合理地得出以下结论: _aimageView
可能是当前对象在概念上“拥有”的图像视图,而onSuccess
是该图像视图“拥有”的完成块。 除非某些其他对象对其有很强的引用,否则“拥有”对象的生存期仅限于其“拥有”对象的生存期。 因此,该块将不会超出图像视图的寿命,而该图像视图也将不会超出当前对象的寿命。
您担心的唯一方法(当块运行时,由self
指向的对象被释放)可能是其他某个对象存储了对_aimageView
或对该块的强引用。 对于该块,一个对象的“成功块”不太可能与其他对象一起存储。 对于图像视图,如果图像视图“属于”当前对象,则不太可能。 (可以想象,它可能存储在自动释放池中或其他东西中;但是自动释放池除了释放之外不会调用其中的东西,所以这不是问题。)
我能想到的唯一例外是,图像视图是由待处理的网络操作还是其他方法保留,完成onSucess
调用onSucess
块。 但是,如果是这种情况,我想说将一个对象同时用作视图和网络操作是不好的设计。 相反,在那种情况下,应该有一个专用的网络操作对象,它是一个局部变量,并在其上设置一个完成块(例如,将图像存储在图像视图中,设置标签等),开始操作,不需要存储操作。 然后,该块可以强烈地引用self
,但是没有保留周期。
总而言之,该块(以及拥有它的图像视图)应根据谁使该块保持活动 (即谁保留它,谁对其保持强烈引用)而属于以下两种类别之一:
如果self
使它保持活动状态:例如,一个视图控制器使它的视图和子视图保持活动状态。 在这种情况下,使用__weak
是安全的,因为该块在self
生命之外不存在。
如果有人让它保持活动状态:例如警报视图,您只需创建并显示它; 系统随后将其保留在屏幕上。 在这种情况下, self
不应(也不需要)对其进行引用,并且可以在块中强烈引用self
。 它不会导致保留周期。
尽量避免self
和他人使自己活着的情况。
因为您需要保证method2
和method3
被执行,所以您需要由self
引用的对象保持活动状态。 为此,请遵循标准模式:在需要时始终保持强烈参考。 您的第二个代码片段将执行此操作。
参考周期并不是天生的坏,而是非托管周期。 在这里,您先做一个循环然后再打破它,所以没有问题。
(请注意,您可以发送一条消息到nil
,如果strongSelf
为nil
,第一个代码片段将不会崩溃-它只会做任何事情。)
-(void)someMethod{
AnotherObject *abc=[[AnotherObject alloc]init];
abc.onSuccess=^{
[self method2];
[self method3];
}
}
这将使。 它不会导致保留周期。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.