在[block copy]
之后执行block();
,我应该设置block=nil
吗?或者ARC已经为我管理了这个,所以我不需要做任何事情?
我对ARC如何管理块引用有点困惑,我不确定将块设置为nil会不会破坏任何内容?
我有类似的东西。有什么想法吗?
typedef void (^C3Block)(void); // declare block, no return, no args
// set flag to get _previewImage, then call the block
- (void)takePreviewImageFromBufferWithBlock:(C3Block)block {
_takePreviewImageBlock = [block copy]; // save block ref for calling later
_shouldTakePreviewImageFromBuffer = YES;
}
- (void)gotPreviewImageFromBuffer {
_takePreviewImageBlock(); // calls the block
_takePreviewImageBlock = nil; // <---- should I do this???
}
答案 0 :(得分:5)
我认为将它设置为nil
是个好主意,原因如下:
让这些方法在ImageLoader
中调用类。假设我有一个类MyViewController
,它强烈引用这个ImageLoader
(比如说它是一个实例变量),并传递一个保留self
的块(即MyViewController
})。为什么保留self
?好吧,你的ImageLoader
大概是异步工作的,所以,比如说,我希望我的MyViewController
足够长,能够处理响应。
好的,我们有一个保留周期。 MyViewController
会保留ImageLoader
,其中会保留该块,并保留MyViewController
。但是,如果在nil
中操作结束时只是ImageLoader
块变量,它将打破此循环。否则,这些对象将永远不会被释放。 ImageLoader
在完成操作时将块变量设置为nil
是有意义的,因为它不再“需要”它。
(您也可以认为,通过以不同方式安排保留可以避免上述方案中的问题 - MyViewController
异步操作ImageLoader
仍然必须由正在进行的操作中的某些保留。ImageLoader
仍保留保留ImageLoader
的块。操作完成后,释放MyViewController
的操作将释放所有内容,每个人都很高兴,无需将块变量设置为ImageLoader
。)
答案 1 :(得分:2)
通常,将块iVar设置为nil是没有意义的,因为您很可能会通过连续-takePreviewImageFromBufferWithBlock:
调用重置它。从内存管理的角度来看,_takePreviewBlock
是一个iVar,它的ARC管理将与任何其他iVar相同 - 当所有者类被解除分配时,它将在没有您的交互的情况下正确发布。
答案 2 :(得分:2)
如果_takePreviewImageBlock
是具有强属性的属性,则只要包含此属性的对象存在,ARC就会保留该属性。
如@Eugene所述,它会在调用takePreviewImageFromBufferWithBlock:
后重置。
了解此行为后,您应该确定它是否适合您的设计。如果所有者将在之后被解除分配,则无需自己取消其属性。否则,如果这个块不再与你的逻辑相关,那么你应该把它弄为零,并且它将无缘无故地存在于内存中。