如果在块中引用self,为什么这不是保留周期?

时间:2015-08-20 09:08:36

标签: ios objective-c cocoa cocoa-touch objective-c-blocks

@interface myViewController ()
@property (nonatomic, copy)  NSString* (^translateKey)(NSString *);
@property (nonatomic, copy) NSString *aString;
@end

案例#1

@implementation
-(void)viewDidLoad {
    _translateKey = ^NSString*(NSString* translationKey){
        return _aString;
    };
}
@end
  • 编译器抱怨#1是保留周期。我理解

例#2

@implementation
-(void)viewDidLoad {
    NSString * (^translationKeyBlock)(NSString *) = ^NSString*(NSString* translationKey){        
        return _aString;
    };
    _translateKey = translationKeyBlock;
}
  • 编译器不会抱怨案例#2。但这仍然是一个保留周期吗?

2 个答案:

答案 0 :(得分:5)

案例2仍然是一个循环?是

为什么错过了?编译器的流分析没有发现这种情况,在这种情况下有点令人惊讶(优化者肯定会将translationKeyBlock减少案例2减少到案例1)。

你应该怎么做?将其作为“增强请求”提交给Apple,或者通过bugreporter.apple.com将其提交为“bug”。他们可能会因为他们没有抓住它而回来,或者他们将来可能会支持它。 (这不是我见过的第一个流量分析问题。)

答案 1 :(得分:1)

我认为你的问题是:

@implementation
-(void)viewDidLoad {
    NSString * (^translationKeyBlock)(NSString *) = ^NSString*(NSString* translationKey){        
        return _aString;
    };
    _translateKey = translationKeyBlock;
}

它仍然是一个保留周期,但编译器不会抱怨。

如果直接将块设置为_translateKey,编译器会发现此行将进行保留循环并抛出错误或警告。 但是,编译器不会确定您是否先将块设置为局部变量。这就是为什么第一行没有抱怨错误。

本地变量translationKeyBlock的值可以在执行前随时更改 _translateKey = translationKeyBlock;

也许原因是编译器在编写代码时无法检查translationKeyBlock的值。(我不确定100%。)

我希望这可以帮到你。