Objective c 通过将一个块作为参数传递,然后复制它,是否可能在ARC下发生内存泄漏?如果是,如何预防?
我正在做一个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]
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属性,则应将该变量设置为弱