繁体   English   中英

ARC,数据块和保留周期

[英]ARC, Blocks and Retain Cycles

使用ARC在针对4.0和5.0的iOS项目上工作。

遇到与块,ARC有关的问题,并从块外部引用对象。 这是一些代码:

 __block AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
   [operation setCompletionBlock:^ {
       if ([operation isCancelled]) {
           return;
       }

... do stuff ...

operation = nil;
}];

在这种情况下,编译器会发出警告,指出在块中使用“操作”将导致保留周期。 在ARC下,__block现在保留变量。

如果我添加__unsafe_unretained,则编译器会立即释放该对象,因此显然无法正常工作。

我的目标是4.0,所以我不能使用__weak。

我试图做这样的事情:

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
__block __unsafe_unretained AFHTTPRequestOperation *weakOperation = operation;

但是,尽管弱操作不是零,但在块内时不会填充其所有属性。

鉴于上面列出的项目限制,解决这种情况的最佳方法是什么?

假设进度保证,那么保留周期可能正是您想要的。 您在块的末尾显式地中断了保留周期,因此它不是永久的保留周期:调用该块时,该周期被中断。

但是,如果还有其他方法可以保留该操作,则可以将引用存储到__weak__unsafe_unretained变量中,然后在您的块中使用它。 除非需要出于某种原因需要在块期间更改变量的绑定,否则不需要__block限定变量的值; 由于您没有再中断的保留周期,因此无需为弱变量分配任何内容。

这似乎是Conrad Stoll在“ 块,操作和保留周期”中描述的问题,但是他的文章遗漏了一些重要点:

  • __block看起来像苹果推荐的方法,它避免在MRC模式下强烈引用捕获的变量,但在ARC模式下完全没有必要。 在这种情况下,在ARC模式下完全没有必要。 尽管较轻量的解决方法更加冗长,但在MRC模式下也没有必要: void * unretainedOperation = operation; ... ^{ AFHTTPRequestOperation * op = unretainedOperation; } void * unretainedOperation = operation; ... ^{ AFHTTPRequestOperation * op = unretainedOperation; }
  • 在ARC模式下,您既需要强引用(因此您可以将其添加到队列中),也需要弱/ unsafe_unretained引用

最简单的解决方案如下所示:

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
AFHTTPRequestOperation * __unsafe_unretained unretainedOperation = operation;

[operation setCompletionBlock:^ {
  if ([unretainedOperation isCancelled]) {
    return;
  }
  ... do stuff ...
}];

即使您中断了参考周期, Block也没有理由将AFHTTPRequestOperation保留在第一位(假定操作在完成处理程序完成之前一直保持活动状态,这并不总是可以保证的,但通常是正确的,并且由ARC假定)如果在调用堆栈的更远处使用self来引用它)。

最好的解决办法似乎是更新到最新的AFNetworking ,它将操作作为参数传递到块中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM