Nic*_*ada 12 asynchronous objective-c ios objective-c-blocks retain-cycle
我正在研究这个代码,它在网上执行一些冗长的异步操作,当它完成时它触发一个完成块,执行一些测试,如果一个变量得到一个值,另一个冗长的操作应该立即开始:
-(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
}
Run Code Online (Sandbox Code Playgroud)
使用此代码,我从编译器收到此警告:
WARNING: Block pointer variable 'completionBlock' is uninitialized when caputerd by the block
Run Code Online (Sandbox Code Playgroud)
我变了:
void(^completionBlock) (id obj, NSError *err, NSURLRequest *request)= ^(id obj,NSError *err, NSURLRequest *request)
Run Code Online (Sandbox Code Playgroud)
在:
__block void(^completionBlock) (id obj, NSError *err, NSURLRequest *request)= ^(id obj,NSError *err, NSURLRequest *request)
Run Code Online (Sandbox Code Playgroud)
但我得到另一个警告:
WARNING 2: Capturing 'completionBlock' strongly in this block is likely to lead to a retain cycle
Run Code Online (Sandbox Code Playgroud)
我怎样才能解决这个问题?
谢谢
尼古拉
Jan*_*ano 29
警告:当块捕获时,块指针变量'completionBlock'未初始化
发生这种情况是因为初始化为递归块的块变量需要__block存储.
__block,否则复制块中的变量,在这种情况下,它们作为参考传递.__block,则将使用对变量的引用来创建块.然后变量将初始化为创建的块,块就可以使用了.警告:在此块中强烈捕获'completionBlock'可能会导致保留周期
发生这种情况是因为块变量是对块的强引用,并且块本身引用了变量(因为正如我们之前看到的那样,变量有一个__block所以它被引用而不是复制).
所以我们需要
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];
};
该名称doLengthyAsynchronousOperationWithCompletionBlock表明该方法可能比创建块的方法范围更长.鉴于编译器不复制作为参数传递的块,此方法的责任是复制此块.如果我们将此块与块感知代码(例如dispatch_async():)一起使用,则会自动发生.
如果我们将这个块分配给一个实例变量,我们需要@property(copy)在块内部对self进行弱引用,但事实并非如此,所以我们只使用self.