ios – 如何在这个块中强力地修复“捕获”块可能导致保留周期“

前端之家收集整理的这篇文章主要介绍了ios – 如何在这个块中强力地修复“捕获”块可能导致保留周期“前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在处理这个代码,它在网络上做了一些冗长的异步操作,当它完成它触发完成块时,执行一些测试,如果一个变量获得一定值,另一个冗长的操作应该立即开始:
-(void) performOperation
{

    void(^completionBlock) (id obj,NSError *err,NSURLRequest *request)= ^(id obj,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
}

有了这个代码,我从编译器得到这个警告:

WARNING: Block pointer variable 'completionBlock' is uninitialized when caputerd by the block

我变了:

void(^completionBlock) (id obj,NSURLRequest *request)

在:

__block void(^completionBlock) (id obj,NSURLRequest *request)

但我得到这个其他警告:

WARNING 2: Capturing 'completionBlock' strongly in this block is likely to lead to a retain cycle

如何解决这个问题?

谢谢

尼古拉

解决方法

WARNING: Block pointer variable ‘completionBlock’ is uninitialized
when captured by the block

这是因为初始化为递归块的块变量需要__block存储.

>复制一个块内的变量,除非用__block声明,在这种情况下它们作为参考传递.
>将递归块分配给块变量时,创建发生在分配之前,并且此类创建触发变量副本.鉴于变量尚未分配,复制的变量将是一个错误的值,并且将在块运行时产生崩溃.
>但是,如果我们添加__block,则将使用对该变量的引用来创建该块.然后变量将被初始化为创建的块,块将可以使用.

WARNING: Capturing ‘completionBlock’ strongly in this block is likely
to lead to a retain cycle

这是因为块变量是对块的强引用,并且块本身引用变量(因为如前所述,变量具有__block,因此被引用而不是复制).

所以我们需要

>一个弱参考块内的强变量.
>而且还有一个强有力的参考,以防止在创建块的方法中释放块.

    void(^ completionBlock) (id obj,NSURLRequest *request);
    void(^ __block __weak weakCompletionBlock) (id obj,NSURLRequest *request);
    weakCompletionBlock = completionBlock = ^(id obj,NSURLRequest *request){
        [self lengthyAsyncMethod:weakCompletionBlock];
    };

名称doLengthyAsynchronousOperationWithCompletionBlock表明该方法可能会超过创建块的方法范围.鉴于编译器不会复制作为参数传递的块,因此该方法有责任复制此块.如果我们正在使用具有块感知代码的块(例如:dispatch_async()),则会自动发生.

如果我们将这个块分配给一个实例变量,我们需要一个@property(copy)和一个对块内部的self的弱引用,但事实并非如此,所以我们只是使用self.

猜你在找的iOS相关文章