Objective c 通过将一个块作为参数传递,然后复制它,是否可能在ARC下发生内存泄漏?如果是,如何预防?

Objective c 通过将一个块作为参数传递,然后复制它,是否可能在ARC下发生内存泄漏?如果是,如何预防?,objective-c,automatic-ref-counting,Objective C,Automatic Ref Counting,我正在做一个Objective-C项目,我们已经启用了ARC。我目前处理的是两个独立的类,我们称它们为A和B A强烈引用了B,B具有具有copy属性的块属性 @interface A { B *b; ... } @end @interface B { ... } @property (copy) void (^myBlock)(); @end 现在,如果在a拥有的方法中,我尝试分配给myBlock: b.myBlock = ^{ [self doSomething]

我正在做一个Objective-C项目,我们已经启用了ARC。我目前处理的是两个独立的类,我们称它们为
A
B

A
强烈引用了
B
B
具有具有
copy
属性的块属性

@interface A {
    B *b;
    ...
}
@end

@interface B {
    ...
}
@property (copy) void (^myBlock)();
@end
现在,如果在
a
拥有的方法中,我尝试分配给
myBlock

b.myBlock = ^{ [self doSomething] };
编译器(正确地)抱怨:

在此块中强烈捕获“自我”可能会导致一个保留周期。

我了解这种行为,以及如何根据问题的答案来解决它。(基本上,形成循环是因为一旦复制块,它将包含对
a
的强引用,该引用对
B
具有强引用,而
B又具有对块本身的强引用。)

现在,如果不是直接将块指定给属性,而是将其传递给B的方法:

[b takeMyBlock:^{ [self doSomething] }];
在我执行赋值的方法中,编译器将不再抱怨

我的问题是:这会造成内存泄漏吗?如果是,如何避免?是否可以以某种方式对方法参数进行注释,以便编译器知道将要复制该参数


提前谢谢。

我自己也遇到了同样的问题。虽然这个问题本身并没有表现为泄漏,但实际上我在使用Instruments中的分配工具分析堆增长时发现了这个问题——因此它显然会导致内存问题

我认为编译器必须非常聪明才能发现问题并发出警告,因此我猜测需要两种方法之一:

  • 文档:正如您在问题中所建议的,清楚地记录文档 此方法将复制传递给它的块。这可能 包括将块参数命名为类似于
    blockToCopy
    (使用时,Xcode可帮助显示块参数名称。) 自动完成)。另外,对方法声明进行注释。如果你是 使用像appledoc这样的文档工具,这特别好, 因为您的文档也将出现在Xcode的快速帮助对话框中 当选项单击您的代码时

  • 永远不要在一个块中强捕获
    self
    这可能是最好的 练习,因为我认为保持强壮的肌肉从来都不是一个好主意 在块内引用
    self
    。如果您必须参考
    self
    , 使用弱引用。这肯定会避免你遇到的情况 描述。(注意:引用实例变量也将保持强 参考
    self


  • 我自己也遇到了同样的问题。虽然这个问题本身并没有表现为泄漏,但实际上我在使用Instruments中的分配工具分析堆增长时发现了这个问题——因此它显然会导致内存问题

    我认为编译器必须非常聪明才能发现问题并发出警告,因此我猜测需要两种方法之一:

  • 文档:正如您在问题中所建议的,清楚地记录文档 此方法将复制传递给它的块。这可能 包括将块参数命名为类似于
    blockToCopy
    (使用时,Xcode可帮助显示块参数名称。) 自动完成)。另外,对方法声明进行注释。如果你是 使用像appledoc这样的文档工具,这特别好, 因为您的文档也将出现在Xcode的快速帮助对话框中 当选项单击您的代码时

  • 永远不要在一个块中强捕获
    self
    这可能是最好的 练习,因为我认为保持强壮的肌肉从来都不是一个好主意 在块内引用
    self
    。如果您必须参考
    self
    , 使用弱引用。这肯定会避免你遇到的情况 描述。(注意:引用实例变量也将保持强 参考
    self


  • 在ARC中,它所做的是当局部变量或弱变量失去引用时。内存将立即解除分配,因为其引用计数为零。但是,如果重新分配强变量,即使引用计数衰减为零,也肯定会导致强变量保留的内存泄漏。在这种情况下,您应该在重新分配之前将该变量设置为NIL,或者如果不需要强属性,则将该变量设置为弱。

    在ARC中,如果局部变量或弱变量失去了它的引用,它将执行此操作。内存将立即解除分配,因为其引用计数为零。但是,如果重新分配强变量,即使引用计数衰减为零,也肯定会导致强变量保留的内存泄漏。在这种情况下,您应该在重新分配之前将该变量设置为NIL,或者如果不需要strong属性,则应将该变量设置为弱