简体   繁体   English

捕获属性值导致通过_property样式保留周期

[英]Caputure property value lead to retain cycle through _property style

I have a class, there's a block proper: 我有一堂课,这里有一个块:

@property(nonatomic, strong) void (^hehe)();

In the init method, I do the following work: 在init方法中,我做了以下工作:

__weak test *weakSelf = self;
self.hehe = ^{
    test *self = weakSelf;
    NSLog(@"%zd", self.a);
    NSLog(@"%zd", self->_a);
    NSLog(@"%zd", _a);
};

What is the difference between the last two line in the block. 该块的最后两行之间有什么区别。

I thought self->_a is equals to _a . 我以为self->_a等于_a

But the Xcode shows warning on the last line: 但是Xcode在最后一行显示警告:

Caputuring self strongly in this block is likely to lead a retain cycle


Edit: 编辑:

I know the local self and the global self is not the same. 我知道本地自我和全球自我是不一样的。 How the os distinguish the difference. 操作系统如何区分差异。 I used clang to rewrite the code, and get the following: 我使用clang重写了代码,并获得了以下信息:

static void __ViewController__init_block_func_0(struct __ViewController__init_block_impl_0 *__cself) {
  __Block_byref_weakSelf_0 *weakSelf = __cself->weakSelf; // bound by ref

    ViewController *self = (weakSelf->__forwarding->weakSelf);
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_gp_6ztdfl3n5919c3y4pb03gd340000gn_T_ViewController_ad5b98_mi_0, ((NSInteger (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("a")));
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_gp_6ztdfl3n5919c3y4pb03gd340000gn_T_ViewController_ad5b98_mi_1, (*(NSInteger *)((char *)self + OBJC_IVAR_$_ViewController$_a)));
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_gp_6ztdfl3n5919c3y4pb03gd340000gn_T_ViewController_ad5b98_mi_2, (*(NSInteger *)((char *)self + OBJC_IVAR_$_ViewController$_a)));
}

The last two line is used the same self... 最后两行使用相同的self ...

Because it means a different self . 因为这意味着不同的self A quick rename will make everything clear : 快速重命名将使一切变得清晰:

__weak test *weakSelf = self;
self.hehe = ^{
    test *strongSelf = weakSelf;
    NSLog(@"%zd", strongSelf.a);
    NSLog(@"%zd", strongSelf->_a);
    NSLog(@"%zd", _a);
};

Now it is clear, that the last line captures self from outside the block. 现在很清楚,最后一行从块外部捕获了self The way you had it named, made it harder to differentiate between the self that was a local variable declared inside a block, and the self that was captured from outside its scope. 你有它命名方式,使得它更难于区分self ,这是一个块内声明的局部变量,并self认为是从它的范围之内拍摄的。

Referring to _a is a direct reference to an instance variable from the enclosing scope. 引用_a是从封闭范围直接引用实例变量。 That implicitly captures self. 那暗含了自我。 It doesn't invoke the property's getter/setter. 它不会调用属性的getter / setter。 It points directly to the instance variable. 它直接指向实例变量。

Don't do that from inside a block that persists. 不要在一个持久的块内执行此操作。 (An "escaping" block, as Apple has started calling it.) Use the weakSelf/strongSelf syntax @Losiowaty showed in his answer. (Apple开始调用它时,这是一个“转义”块。)使用他的答案中显示的weakSelf / strongSelf语法@Losiowaty。

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

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