有什么简单的规则可以避免Objective-C块保留周期内存泄漏? [英] What is a simple rule to avoid objective-c block retain cycle memory leaks?

查看:105
本文介绍了有什么简单的规则可以避免Objective-C块保留周期内存泄漏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了由于块保留周期引起的内存泄漏.我只想将一条简单的规则应用到我的代码中,以确保避免使用它们.另一方面,我不想在没有必要的情况下将一半代码库更新为__weak指针.

I've had it with memory leaks arising from block retain cycles. I would just like a simple rule that I can apply to my code to make sure I avoid them. On the other hand, I don't want to update half of my code base base to __weak pointers without it being necessary.

这是我到目前为止所拥有的:

Here is what I have up to now:

使用以下选项时,不会出现内存泄漏:

There can be no memory leaks when you use the following:

dispatch_async(queue, ^{...}); // GCD call.
[Foo bar:^{...}]; // Class "+" methods with completion block.

但是,这些情况肯定会导致块保留周期内存泄漏:

However, these cases will cause block retain cycle memory leaks for sure:

self.myPropertyBlock = ^{ self; };
_myInstanceVariableBlock = ^{ self; };
self.myPropertyBlock = ^{ _selfInstanceVariable; };
obj.myPropertyBlock = ^{ obj; };

这些情况可能会或可能不会导致块保留周期内存泄漏(取决于块调用对象是否保留了该块):

And these cases might or might not cause block retain cycle memory leaks (depending on if the block calling object retains the block):

[self bar:^{ self; }];    
[self.myPropertyObj bar:^{ self; }];
[self.myPropertyObj bar:^{ _selfInstanceVariable; }];

[obj bar:^{ obj; }];
[obj.myPropertyObj bar:^{ obj; }];

为了绝对确定没有内存泄漏,有问题的情况需要将块内使用的selfobj指针更改为__weak指针,如下所示(或其他避免泄漏的策略):

To be absolutely sure there can be no memory leaks, the problematic cases require to change the self or obj pointers used inside the blocks to __weak pointers like this (or some other leak avoiding strategy):

__weak SelfClass *weakSelf = self;
self.myPropertyBlock = ^{ weakSelf; };
_myInstanceVariableBlock = ^{ weakSelf; };
self.myPropertyBlock = ^{ weakSelf.instanceVariableConvertedToProperty; };
[self bar:^{ weakSelf; }];
[self.myPropertyObj bar:^{ weakSelf; }];
[self.myPropertyObj bar:^{ weakSelf.instanceVariableConvertedToProperty; }];

__weak ObjClass *weakObj = obj
[obj bar:^{ weakObj; }];
[obj.myPropertyObj bar:^{ weakObj; }];
obj.myPropertyBlock = ^{ weakObj; };

如果上面有任何错误的情况,请提醒我.

Please alert me about any wrong cases above.

有更简单,更好的规则吗?

Are there simpler and better rules?

如果您可以添加一些解释来解释规则为什么起作用或不起作用,那将是很棒的事情.

It would be awesome if you could add a little explanation explaining why a rule works or doesn't.

基于答案的规则:考虑该块中提到的所有对象并询问,这些对象中的任何一个是否保留了该块?

推荐答案

保留周期是A-> B-> A(其中->表示保留).这很糟糕,因为我们无法取消分配保留的内容,因此取消分配A的唯一方法是取消分配B,但这取决于取消分配A.

A retain cycle is when A -> B -> A (where -> means retains). It's bad because we cannot deallocate retained things, so the only way to deallocate A is to deallocate B, but that depends on deallocating A.

块保留周期没有什么不同,只是块在保留方面更具侵略性:它们保留其中引用的任何对象,因此,如果A-> Block和Block提及A,则A-> Block-> A.

A block retain cycle is no different, except blocks are more aggressive about retaining: They retain any object referenced within them, so if A -> Block and Block mentions A, then A -> Block -> A.

所有这些导致在编码块时产生一个简单的规则.考虑一下该块中提到的所有对象,然后问,这些对象中的任何一个是否保留了该块?大多数时候他们不这样做.但是要特别注意要传递块的对象,换句话说:

All this leads to a simple rule when coding blocks. Consider all of the objects mentioned in the block and ask, do any of these objects retain this block? Most of the time they don't. But pay special attention to the object you're passing the block to, in other words:

[beSuspiciousOfMe heresABlock:^{
    NSLog(@"does %@ retain this block?", beSuspiciousOfMe];
}];

如果您控制beSuspiciousOfMe(可以是并且经常是自我的),则很容易检查.如果由于某种原因该代码不透明,并且您不确定,可以使用__weak copy技巧.

If you control beSuspiciousOfMe (which can be, and often is self), this is easy to check. If that code is opaque for some reason, and you're not sure, you can use the __weak copy trick.

这篇关于有什么简单的规则可以避免Objective-C块保留周期内存泄漏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆