带有块和保留循环的 ARC

Posted

技术标签:

【中文标题】带有块和保留循环的 ARC【英文标题】:ARC with blocks and retain cycles 【发布时间】:2012-07-26 16:02:22 【问题描述】:

我有一个将块作为对象属性的类:

@property (nonatomic, readwrite, copy) SFFailureBlock failureBlock;

SFFailureBlock:

typedef void (^SFFailureBlock)(NSError *error);

我有一个操作也声明为对象属性 (AFHTTPRequestOperation),我希望它在完成后调用失败块。

    [self.operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) 
    __weak NSError *error = [NSError errorWithDomain:@"com.test" code:100 userInfo:@@"description": @"zero results"];
    failureBlock(error);
 failure:^(AFHTTPRequestOperation *operation, NSError *error) 
    NSLog(@"nothing");
];

我收到一个编译器警告“在此块中强烈捕获 'self' 可能会导致保留周期”。我已经搜索了互联网,但我找不到一个体面的解决方案来解释为什么这会导致保留周期。我不会在任何地方的块内调用“自我”。

另一个奇怪的事情是,如果我写了'self.failureBlock(error)',编译器不会给我任何警告!

谁能向我解释发生了什么事?我一定严重遗漏了 ARC 内存管理规则中的某些内容,但我无法弄清楚。

【问题讨论】:

【参考方案1】:

当您在操作块中引用“failureBlock”时,您实际上是在执行“self-> failureBlock” - 所以它隐含地保留了 self。您可以做的是创建一个自动变量 SFFailureBlock xFailureBlock = failureBlock;上面的self操作,然后在block中使用它。 [再一次,你要避免任何 self-> INSIDE 的引用。]

【讨论】:

除非我弄错了,否则将示例中的 xFailureBlock 设置为 __weak 或 __unsafe_unretained 也是一个好主意。 我相信但不确定失败块的 xFailure auto var 是否会复制该块(然后被封闭块捕获)。 我明白了。但是,failureblock 不是控制器的实例属性吗?我认为一般来说,当我们执行“[self.myarray addObject:anObject];”之类的操作时在块内,则不保留“myArray”。我错了吗? 如果您建站,self 会被保留。就像您单独使用 myarray 一样。我在 Apple 的 ObjectiveC listserv 上发布了同样的问题,得到了这个答案:“当你在一个块中引用一个 Objective-C 实例变量时,self 被关闭,而不是变量本身。就好像你写了 self->foo = 是的; " 我忘了在上面提到的是苹果工程师提供了答案。

以上是关于带有块和保留循环的 ARC的主要内容,如果未能解决你的问题,请参考以下文章

ARC 如何确定是使用保留还是复制?

使用Objective-C中的单例保留循环

ARC圆形保留检测

使用 ARC 查找对象的保留位置

为啥在启用 ARC 的项目中不需要维护保留计数

使用 ARC 手动保留