csotiriou csotiriou - 29 days ago 20
iOS Question

ARC with blocks and retain cycles

I have a class which holds a block as an object property:

@property (nonatomic, readwrite, copy) SFFailureBlock failureBlock;


where SFFailureBlock:

typedef void (^SFFailureBlock)(NSError *error);


I have an operation also declared as an object property (AFHTTPRequestOperation) and I want it to call the failure block once it is completed.

[self.operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
__weak NSError *error = [NSError errorWithDomain:@"com.test" code:100 userInfo:@{@"description": @"zero results"}];
failureBlock(error);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"nothing");
}];


I get a compiler warning "Capturing 'self' strongly in this block is likely to lead to a retain cycle". I have searched the internet but I couldn't find a decent solution as to why this leads to a retain cycle. I am not calling 'self' inside the block anywhere.

Another strange thing is that if I write 'self.failureBlock(error)' the compiler does not give me any warning!

Can anyone explain to me what is going on? I must be seriously missing something in ARC memory management rules, but I can't figure it out.

Answer

When you refer to "failureBlock" in the operation's block, you are really doing "self-> failureBlock" - so it implicitly retains self. What you can do is create an automatic variable SFFailureBlock xFailureBlock = failureBlock; above the selfoperation, then use it in the block. [Again, you want to avoid any self-> references INSIDE that block either.]