2
votes

I'm using blocks to handle the response of async http requests in a non-ARC project. The code looks like this (the relevant parts):

NSMutableUrlRequest* request = ...;
__block typeof(self) mutableSelf = self;

void (^didGetSessionBlock)(Gopher* newGopher) = ^(Gopher* newGopher) {
    if (newGopher.statusCode == HTTP_OK) {
        ...
        mutableSelf.retryOnFail = NO;
        [mutableSelf executeRequest:request];
    }

    ...
    [mutableSelf setStatusCode:newGopher.statusCode];
};

Gopher* newGopher = [[[Gopher alloc] init] autorelease];

[newGopher setDidCompleteBlock:didGetSessionBlock];
[newGopher fetchSession:myApp.settings.userName password:myApp.settings.password];

__block mutableSelf is used so that I can modify self inside of the block (and not a copy of self). The __block keyword, if I understand correctly, also has the effect that mutableSelf is not retained so it might already be released when the block is executing (and this is exactly what happens).

If I change

[mutableSelf executeRequest:request];

to

[self executeRequest:request];

all is well since self gets retained and won't be released until the block has executed. However, directly referencing self might cause leaks due to retain cycles.

Is there a way around this? Should I manually retain mutableSelf when it's declared and then release it inside of the block? Or should I use self inside the block where I'm not modifying it, potentially creating a leak? Both variants seem fragile and need explanations in comments to avoid confusion and future bugs if/when the code is modified.

Is there a way to solve this problem? If not, what is the best approach?

1
You might like to have a look at Retain cycle on self with Blocks and its answers. - jscs

1 Answers

3
votes

You don't modify self in the block, you only modify the object pointed to by it. I don't think you need __block.