避免objective-c块保留周期内存泄漏的简单规则是什么?



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

这是我到目前为止的资料:

当您使用以下命令时,可以不存在内存泄漏:

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

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

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

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

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

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

__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; };

请提醒我以上任何错误的情况。

有更简单更好的规则吗?

如果你能加上一点解释,解释为什么一个规则有效或不有效,那就太棒了。

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

保留周期是A -> B -> A(其中->表示保留)。这很糟糕,因为我们不能释放保留的东西,所以释放A的唯一方法是释放B,但这取决于释放A。

一个块保留周期没有什么不同,除了块更积极地保留:它们保留在它们内部引用的任何对象,所以如果A -> block和block提到A,那么A -> block -> A

所有这些导致了编码块时的一个简单规则。考虑区块中提到的所有对象,并问,这些对象是否保留了这个区块?大多数时候他们不会。但是要特别注意传递块的对象,换句话说:

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

如果你控制besusiciousofme(它可以是,而且通常是self),这很容易检查。如果代码由于某种原因是不透明的,并且你不确定,你可以使用__weak copy技巧。

最新更新