我应该在执行后将块引用设置为nil吗?

时间:2013-01-31 19:19:53

标签: ios objective-c objective-c-blocks

[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???
}

3 个答案:

答案 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:后重置。

了解此行为后,您应该确定它是否适合您的设计。如果所有者将在之后被解除分配,则无需自己取消其属性。否则,如果这个块不再与你的逻辑相关,那么你应该把它弄为零,并且它将无缘无故地存在于内存中。