使用自身保留Obj-C块上的循环 [英] Retain cycle on an Obj-C block using itself

查看:91
本文介绍了使用自身保留Obj-C块上的循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个块用作NSURLConnection异步请求的完成处理程序,其主要工作是使用与新请求完成处理程序相同的块来生成新的异步请求.我这样做是因为它有效地解决了另一个问题,该问题是排队一系列异步调用并在后台将其触发.对于我们来说,这是一项了不起的工作,但是我们有一个警告我很担心.即,XCode认为我有一个保留周期.也许我知道,我不知道.在过去的几个小时中,我一直在尝试学习有关块的知识,但是我还没有找到关于像我这样的递归用法的解释.警告状态阻止将被捕获的对象保留".

I have a block to use as a completionHandler for an NSURLConnection asynchronous request whose main job is to spawn a new asynchronous request using the same block for the new requests completion handler. I am doing this because it effectively solves another problem which is to line up a sequence of asynchronous calls and have them fired off in the background. This is working marvelously for us, but we have a warning I am concerned about. Namely, XCode thinks I have a retain cycle. Perhaps I do, I don't know. I've been trying to learn about blocks over the last couple hours but I haven't found an explanation for recursive uses like mine. The warning states `Block will be retained by the captured object'.

到目前为止,我最好的猜测是保留周期正是我们想要的,并且要清除完成后的内容,我们只需对正在执行的block变量进行nill化即可.它不能消除错误,但是只要我不泄漏内存或做一些我不知道的黑魔法,我都不会介意.谁能解决这个问题?我处理正确吗?如果没有,我该怎么办?

My best guess so far is that a retain cycle is exactly what we want, and that to clear when we are done, we just nillify the block variable, which I'm doing. It doesn't get rid of the error, but I don't mind as long as I'm not leaking memory or doing some black magic I'm not aware of. Can anyone address this? Am I handling it right? If not, what should I be doing?

void (^ __block handler)(NSURLResponse *, NSData *, NSError*);
handler = ^(NSURLResponse *response, NSData *data, NSError *error)
{
    [dataArray addObject:data];

    if (++currentRequestIndex < [requestsArray count])
    {

        if (error)
        {
            [delegate requestsProcessWithIdentifier:_identifier processStoppedOnRequestNumber:currentRequestIndex-1 withError:error];
            return;
        }

        [delegate requestsProcessWithIdentifier:_identifier completedRequestNumber:currentRequestIndex-1]; // completed previous request

        [NSURLConnection sendAsynchronousRequest:[requestsArray objectAtIndex:currentRequestIndex]
                                           queue:[NSOperationQueue mainQueue]
                               completionHandler:handler]; // HERE IS THE WARNING
    }
    else
    {
        [delegate requestsProcessWithIdentifier:_identifier completedWithData:dataArray];
        handler = nil;
    }
};
[NSURLConnection sendAsynchronousRequest:[requestsArray objectAtIndex:0]
                                   queue:[NSOperationQueue mainQueue]
                       completionHandler:handler];

推荐答案

尝试将handler块存储到视图控制器(或您所在的任何类)的实例变量中.

Try to store your handler block into an instance variable of your view controller (or whatever class you're in).

假设您声明了一个名为_hander的实例变量:

Assuming that you declare an instance variable named _hander:

{
  void (^_handler)(NSURLResponse *, NSData *, NSError*);
}

将您的代码更改为:

__weak __typeof(&*self)weakSelf = self;
_handler = ^(NSURLResponse *response, NSData *data, NSError *error)
{
  [dataArray addObject:data];

  if (++currentRequestIndex < [requestsArray count])
  {

    if (error)
    {
      [delegate requestsProcessWithIdentifier:_identifier processStoppedOnRequestNumber:currentRequestIndex-1 withError:error];
      return;
    }

    [delegate requestsProcessWithIdentifier:_identifier completedRequestNumber:currentRequestIndex-1]; // completed previous request

    __strong __typeof(&*self)strongSelf = weakSelf;
    [NSURLConnection sendAsynchronousRequest:[requestsArray objectAtIndex:currentRequestIndex]
                                       queue:[NSOperationQueue mainQueue]
                           completionHandler:strongSelf->_handler];
  }
  else
  {
    [delegate requestsProcessWithIdentifier:_identifier completedWithData:dataArray];
  }
};

[NSURLConnection sendAsynchronousRequest:[requestsArray objectAtIndex:0]
                                   queue:[NSOperationQueue mainQueue]
                       completionHandler:_handler];

这篇关于使用自身保留Obj-C块上的循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆