Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I release an object with a block completion handler under ARC?

It’s a common pattern in my code to allocate an object, let it do some stuff with a completion handler and release it in the handler:

LongOperation *foo = [[LongOperation alloc] init];
[foo runWithCompletion:^{
    // run some code and then:
    [foo autorelease];
}];

This works fairly well, but when I attempt to convert the code to ARC, Xcode rightly complains that it can’t simply drop the autorelease from the block, since that would make the foo object get deallocated after leaving the scope.

So what’s a good way to write this kind of pattern under ARC? I could introduce an instance variable for foo:

[self setFoo:[[LongOperation alloc] init]];
[foo runWithCompletion:^{
    // run some code and then:
    [self setFoo:nil];
}];

…but the code would not be re-entrant anymore.

like image 524
zoul Avatar asked Jan 04 '12 08:01

zoul


1 Answers

In most cases, it should work (i.e., if anything references self inside of foo, foo will last long enough to satisfy that code before going away). If there are issues with weak references and such that foo looks like it should go away but shouldn't until after the handler runs, you can do something like:

__block LongOperation* foo = [[LongOperation alloc] init];
[foo runWithCompletion:^{
  // do some things
  foo = nil;
}];

Note this is kind of the opposite of this pattern which causes the object /not/ to be captured under managed memory rules.

like image 155
Jason Coco Avatar answered Sep 23 '22 14:09

Jason Coco