【问题标题】:Why is self retained in a block that accesses one of its properties?为什么 self 保留在访问其属性之一的块中?
【发布时间】:2013-01-12 01:40:33
【问题描述】:

在下面的代码中,self 被保留以确保图像对象在块被调用时仍然存在。这就是文档所说的。但是,我似乎不明白为什么。简单地保留图像就可以保证它不会被释放。那么为什么还要保留自我呢?

self.finishBlock = ^{
    self.image.hidden = YES;
}

如果您直接访问图像,这是否适用?

self.finishBlock = ^{
    _image.hidden = YES;
}

【问题讨论】:

    标签: iphone ios objective-c ipad automatic-ref-counting


    【解决方案1】:

    self 被保留是因为

    self.image.hidden = YES;
    

    其实是

    [[self image] setHidden:YES];
    

    图像不能/不能直接保留,因为在执行块并调用[self image] 获取图像之前它不可用。

    您的第二个示例也保留了 self,但原因略有不同。在 Objective-C 中,当你直接访问一个实例变量时,它实际上是通过 self 的底层结构访问的。所以,_image 在编译后实际上就是self->_image。同样,该块需要访问自我,因此它保留自我。

    另外值得注意的是,无论哪种情况,如果 _image 的值在块执行之前发生变化,块将“看到”新值。这通常是你想要的,但并不总是你想要的。

    您有两种选择来避免保留自我。第一个会这样做并且将在定义块时捕获_image的值,因此即使它发生变化,块也会看到原始值。这种方法是定义一个局部变量,将其设置为self.image返回的当前值,然后在块中使用:

    UIImage *image = self.image;
    self.finishBlock = ^{
        image.hidden = YES;
    }
    

    另一种方法是捕获 self 的弱版本并在块中使用它。在这种情况下,块将有一个弱的——而不是强的——对 self 的引用(即不会保留 self)。但是,self 上的-image 访问器方法仍然会被调用,因此如果在块运行之前更改图像,将使用新值:

    __weak YourClass *weakSelf = self;
    self.finishBlock = ^{
        weakSelf.image.hidden = YES;
    }
    

    请注意,在这种情况下,如果 self 在块运行之前被释放,weakSelf 将为 nil,并且块中的语句将有效地成为 NOOP(发送到 nil 的消息在 Objective 中不做任何事情-C)。

    【讨论】:

    • 第一个示例中的方法调用非常合理。但是,在第二个例子中,self 会被保留吗?
    • 我在原来的答案中说错了。我已将其更新为更彻底/准确。 self is 仍然保留在您的第二个示例中。
    • +1 也说明了这一点,但我觉得有义务向 @rmaddy 提出问题,因为他是第一个注意到 self->_image 事情的人。
    【解决方案2】:

    块需要在块中保留任何捕获的对象。您的第一个块示例确实是:

    self.finishBlock = ^{
        [[self image] setHidden:YES];
    }
    

    该块必须保留self,以便它可以正确调用image 方法。正如所写的那样,块不能简单地保留image,因为直到执行块并调用image 方法才获得图像。所以这里唯一的选择是保留self

    在第二块你真的有:

    self.finishBlock = ^{
        self->_image.hidden = YES;
    }
    

    同样,self 必须保留,以便在实际执行块时访问 _image ivar 的正确值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-08
      • 2012-04-25
      • 1970-01-01
      • 1970-01-01
      • 2017-03-04
      • 1970-01-01
      • 2022-01-20
      相关资源
      最近更新 更多