Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I set block reference to nil AFTER execution?

After [block copy] and executed block();, should I set block=nil? Or does ARC already manage this for me so I don't have to do anything? I'm a bit confused on how ARC manages block references here and I'm not sure setting the block to nil would break anything or not?

I have something like this. Any thoughts?

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???
}
like image 510
Hlung Avatar asked Jan 14 '23 08:01

Hlung


2 Answers

I think it's a good idea to set it to nil, and here is why:

Let's call the class these methods are in ImageLoader. Suppose I have a class MyViewController that has a strong reference to this ImageLoader (it's an instance variable, say), and passes it a block that retains self (i.e. the MyViewController). Why does it retain self? Well, your ImageLoader presumably works asynchronously, so, say, I want my MyViewController to be around long enough to handle the response.

Okay, so we have a retain cycle. The MyViewController retains the ImageLoader, which retains the block, which retains the MyViewController. However, if you simply nil the block variable at the end of the operation in ImageLoader, it will break this cycle. Otherwise these objects will never be deallocated. It kind of makes sense for ImageLoader to set the block variable to nil when its operation is done because it no longer "needs" it.

(You could also argue that the issue in the scenario above could be avoided by arranging the retains differently -- that MyViewController should not retain ImageLoader. Then, during the asynchronous operation, ImageLoader must still be retained by something from the ongoing operation. ImageLoader still retains the block which retains MyViewController. When the operation is done, the operation releasing ImageLoader will release everything, and everyone is happy, without needing to set the block variable to nil.)

like image 68
newacct Avatar answered Jan 29 '23 11:01

newacct


Generally, there's no point in setting your block iVar to nil, since you most probably will reset it with the consecutive -takePreviewImageFromBufferWithBlock: call. From memory management point of view, _takePreviewBlock is an iVar and it's management by ARC will be the same as with any other iVar - it'll be properly released without your interaction when the owner class gets deallocated.

like image 37
Eugene Avatar answered Jan 29 '23 11:01

Eugene