Should I set the block reference to nil after execution?

After [block copy]

and after executing block();

, should I install block=nil

? Or is ARC already handling this for me, so I don't have to do anything? I'm a little confused about how ARC manages block references here and I'm not sure if setting a 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???
}

      

+3


source to share


3 answers


I think it's a good idea to set it to nil

, and here's why:

Let the class call these methods are in ImageLoader

. Suppose I have a class MyViewController

that has a strong reference to this one ImageLoader

(it is an instance variable, for example) and passes it a block that saves self

(i.e. MyViewController

). Why does he save self

? Well, yours ImageLoader

presumably runs asynchronously, so let's say I want mine MyViewController

to be long enough to handle the response.



So we have a retention cycle. MyViewController

saves ImageLoader

, which saves the block, which saves MyViewController

. However, if you are just a nil

block variable at the end of an operation in ImageLoader

, it will break this loop. Otherwise, these objects will never be freed. It ImageLoader

makes sense to set a block variable to nil

when its operation is in progress, because it no longer "needs" it.

(You could also argue that the problem in the above scenario could have been avoided by ordering the save differently - so that it MyViewController

doesn't save ImageLoader

. Then, during the asynchronous operation ImageLoader

, some of the current operation is ImageLoader

still saved . It still saves the block that saves MyViewController

. When the operation is complete, the operation that frees ImageLoader

will release everything and everyone is happy, without having to set the block variable in nil

.)

+5


source


There is generally no point in setting your iVar block to zero as you will most likely be reset with a sequential call -takePreviewImageFromBufferWithBlock:

. In terms of memory management, _takePreviewBlock

is an iVar, and ARC control will be the same as with any other iVar - it will be properly released without your interaction when the owner class is released.



+2


source


If _takePreviewImageBlock

is a property with a strong attribute , then ARC will keep it as long as the object containing this property exists.
As @Eugene mentioned it will be reset after being called takePreviewImageFromBufferWithBlock:

.

Once you understand this behavior, you must decide if it fits your design. If the owner is released immediately thereafter, there is no need to strip them of their properties on their own. Otherwise, you should use it if that block is no longer relevant to your logic and it will sit in memory for a good reason.

+2


source







All Articles