I am working on this code, which does some lengthy asyncronous operation on the net and when it finishes it triggers a completion block where some test is executed and if a variable get a certain value another lengthy operation should start immediately:
-(void) performOperation
{
void(^completionBlock) (id obj, NSError *err, NSURLRequest *request)= ^(id obj,NSError *err, NSURLRequest *request){
int variable=0;
// Do completion operation A
//...
//...
// Do completion operation B
//Get the variable value
if(variable>0){
[self doLengthyAsynchronousOperationWithCompletionBlock: completionBlock];
}
};
//Perform the lenhgty operation with the above completionBlock
[self doLengthyAsynchronousOperationWithCompletionBlock: completionBlock];
}
-(void) doLengthyAsynchronousOperationWithCompletionBlock: completionBlock
{
//Do some lengthy asynchronous stuff
}
With this code I get this warning from the compiler:
WARNING: Block pointer variable 'completionBlock' is uninitialized when caputerd by the block
I changed:
void(^completionBlock) (id obj, NSError *err, NSURLRequest *request)= ^(id obj,NSError *err, NSURLRequest *request)
in:
__block void(^completionBlock) (id obj, NSError *err, NSURLRequest *request)= ^(id obj,NSError *err, NSURLRequest *request)
but I get this other warning:
WARNING 2: Capturing 'completionBlock' strongly in this block is likely to lead to a retain cycle
How can I fix this?
Thanks
Nicola
WARNING: Block pointer variable 'completionBlock' is uninitialized when captured by the block
This happens because block variables initialized to a recursive block need __block
storage.
__block
, in which case they are passed as reference. __block
, the block will be created with a reference to the variable instead. Then the variable will be initialized to the created block, and the block will be ready to use. WARNING: Capturing 'completionBlock' strongly in this block is likely to lead to a retain cycle
This happens because a block variable is a strong reference to the block, and the block is itself referencing the variable (because as we saw before, the variable has a __block
so it is referenced instead copied).
So we need
void(^ completionBlock) (id obj, NSError *err, NSURLRequest *request); void(^ __block __weak weakCompletionBlock) (id obj, NSError *err, NSURLRequest *request); weakCompletionBlock = completionBlock = ^(id obj,NSError *err, NSURLRequest *request){ [self lengthyAsyncMethod:weakCompletionBlock]; };
The name doLengthyAsynchronousOperationWithCompletionBlock
suggests that the method may outlive the method scope where the block is created. Given that the compiler doesn't copy a block passed as an argument, it's responsibility of this method to copy this block. If we are using this block with block aware code (eg: dispatch_async()
), this happens automatically.
Had we been assigning this block to an instance variable, we would need a @property(copy)
and a weak reference to self inside the block, but this is not the case, so we just use self.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.