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???
}
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
.)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With