以下哪个代码部分是正确的?
正确定义"我":
-
它不应该有保留周期,因此不应泄漏。
-
它必须保证method2和method3的运行。 所以块中的MyObject变量绝不能是nil。(可能出现在__weak定义中......)(我不想检查它是否为nil以防止崩溃。我总是希望它是非零的)
更新:(附加信息)
仪器工具确实显示奇怪的泄漏,直到我用__weak替换__block。 然而,在那之后,我记得__弱引用可能随时消失。 我必须确保它不会消失并且也会泄漏。 我没有计时器。 someMethod在观察特定NSNotification时在主线程上调用。
@implementation MyObject...
1 2 3 4 5 6 7 8 9 10
| -(void)someMethod{
AnotherObject *abc=[[AnotherObject alloc]init];
__weak MyObject *weakSelf=self;
abc.onSuccess=^{
__strong MyObject * strongSelf = weakSelf;
[strongSelf method2];
[strongSelf method3];
}
} |
要么
1 2 3 4 5 6 7 8 9 10 11 12 13
| @implementation MyObject...
-(void)someMethod{
AnotherObject *abc=[[AnotherObject alloc]init];
__block MyObject *blockSelf=self;
abc.onSuccess=^{
[blockSelf method2];
[blockSelf method3];
blockSelf=nil;
}
} |
更新2:如果我不使用__weak总是泄漏的实际代码:
1 2 3 4 5
| __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块。但如果是这种情况,我会说将单个对象同时用作视图和网络操作是不好的设计。相反,在这种情况下,应该有一个专用的网络操作对象,它是一个局部变量,并在其上设置一个完成块(例如在图像视图中存储图像,设置标签等),启动操作,不需要存储操作。然后块可以强烈引用self,但没有保留周期。
总而言之,块(以及拥有它的图像视图)应该分为两类,基于谁保持它活着(即谁保留它,谁保持它的强引用):
尽量避免self和其他人保持活着的情况。
-
谢谢你这个详细的答案。"Self"是一个自定义UIButton,在其视图中插入了ImageView。你是对的; _aimageView是@property(非原子的,强大的)AutomatedImageView类,它是UIImageView的手动创建的子类:它会自动下载并显示您猜到的图像。我使用onSuccess来执行其他操作。使用工具"保留周期"部分时,图形显示:self(自定义UIButton)保留imageview,imageview保留自己。(由__block引起)
-
所以我不知道为什么会这样。因为我从superview中删除self(按钮)并将按钮(self)设置为nil。当我在dealloc方法中记录按钮时,该按钮被释放。我也尝试在self(按钮)的dealloc内手动设置onSuccess到nil和_aimageView到nil,但它没有用。据我了解,如果自己还活着,__weak将不会被取消。我认为即使它的主人还活着,它也可能随机变成空洞。这解决了我的问题。 (顺便说一句,如果__block总是在这种情况下创建保留周期,那将是很好的理解)。
-
@frankish:如果块具有对该按钮的弱引用,并且如果没有其他对该按钮的引用,则该按钮将被取消分配。我仍然认为这在这里最有意义,因为所有块正在做的是更新UI元素,如果按钮不再被其他人使用,这是没有意义的。此外,仪器没有"保留周期"仪器,所以我不知道你在说什么。
-
是的,只要按钮在UI上时它永远不会使我的__weak引用为null,对我来说没问题。 我错误地输入了仪器中"保留周期"部分的标题。 正确的一个:当我选择"泄漏"并从工具中心的选项卡中选择"循环和根"时,我会看到乐器中的循环(默认情况下显示"泄漏")(恰好在Snaphots标题的右侧))
一个块可以提到self而不会导致任何泄漏。所以要做的第一件事是指定情况。为什么你认为你的块泄漏了?你检查过吗?如果没有理由担心,没有必要担心。
如果块提到self确实导致泄漏,那么您可以采取的步骤取决于发生这种情况的原因。但是你没有告诉我们。例如,提到self的调度计时器块可能会导致保留周期,但是当您完成计时器后,您可以打破周期,因此没有泄漏。
因此,最好是理解一个特定的保留周期,而不是在不必要的时候对每个块进行防御性编程。
编辑(回应你的评论)我的书中的代码演示了在NSNotification观察者情况下处理内存管理的各种方法:点击这里
-
你好亚光,谢谢你的回答。仪器工具确实显示奇怪的泄漏,直到我用__weak替换__block。然而,在那之后,我记得__弱引用可能随时消失。我必须确保它不会消失并且也会泄漏。我没有计时器。当观察到特定的NSNotification时,在主线程上调用此someMethod。
-
好的,好消息。但是你应该在你的问题中说,因为还有其他方法可以打破NSNotification观察者的保留周期而不是弱强舞。 (虽然在这种情况下我实际上更喜欢弱强舞。)
-
我的书中的代码演示了在NSNotification观察者情况下处理内存管理的各种方法:github.com/mattneub/Programming-iOS-Book-Examples/blob/master/
-
谢谢!很棒的链接。但是,这不是我所拥有的情况。通知在全球范围内广播,观察者应始终观察通知,直到申请结束。在你的"强舞"情况下,你检查是否(_self)。我不应该检查它,它应该总是必须是非"在我的情况下"。我用原始代码更新了问题(添加到问题的底部)
1 2 3 4 5 6 7
| -(void)someMethod{
AnotherObject *abc=[[AnotherObject alloc]init];
abc.onSuccess=^{
[self method2];
[self method3];
}
} |
这将使。它不会导致保留周期。
由于您需要保证执行method2和method3,因此您需要self引用的对象保持活动状态。为此,请遵循标准模式:只要您需要,请保留强大的参考。你的第二个代码片段做到了。
参考周期本身并不坏,它是非托管的。在这里你做一个循环,然后打破它,所以没有问题。
(注意,因为你可以向nil发送消息,如果strongSelf是nil,第一个代码片段不会崩溃 - 它只是不会做任何事情。)
-
谢谢您的回答。那么,将blockSelf设置为nil就像第二个代码片段一样,可以吗?你的意思是说"然后打破它,所以没有问题"这句话?
-
@frankish - 当然,您总是可以将变量设置为nil(假设您没有丢失程序当前需要的引用!)。设置对nil的引用是打破循环的标准方法。
-
我更新了问题并将实际代码添加到底部,如果我使用__block,它总是泄漏。我尝试了各种各样的东西,但它总是泄露,直到我用__weak替换__block。
-
@frankish - 我不能说你的情况发生了什么,你需要进一步探索。如果你打破循环,你不会因循环而泄漏。在此代码中,通过将nil分配给循环中的链接的块来中断循环,这需要调用块。如果使用弱引用,则不需要调用块作为首先创建的无循环。也许那是你的不同之处?