避免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 – >块和块提到A,则A – >块 – > A.

所有这些在编码块时都会产生一个简单的规则。 考虑块中提到的所有对象并询问,这些对象中的任何一个都保留此块吗? 大多数时候他们没有。 但要特别注意你传递块的对象,换句话说:

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

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