在下面的代码中,self 被保留以确保图像对象在块被调用时仍然存在。这就是文档所说的。但是,我似乎不明白为什么。简单地保留图像就可以保证它不会被释放。那么,为什么还要保留自我呢?
self.finishBlock = ^{
self.image.hidden = YES;
}
如果您直接访问图像,这是否适用?
self.finishBlock = ^{
_image.hidden = YES;
}
在下面的代码中,self 被保留以确保图像对象在块被调用时仍然存在。这就是文档所说的。但是,我似乎不明白为什么。简单地保留图像就可以保证它不会被释放。那么,为什么还要保留自我呢?
self.finishBlock = ^{
self.image.hidden = YES;
}
如果您直接访问图像,这是否适用?
self.finishBlock = ^{
_image.hidden = YES;
}
自我保留,因为
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)。但是,-image
self 上的访问器方法仍然会被调用,因此如果在块运行之前更改了图像,则将使用新值:
__weak YourClass *weakSelf = self;
self.finishBlock = ^{
weakSelf.image.hidden = YES;
}
请注意,在这种情况下,如果self
在块运行之前释放,weakSelf
将为 nil,并且块中的语句将有效地成为 NOOP(发送到 nil 的消息在 Objective-C 中不做任何事情)。
块需要在块中保留任何捕获的对象。您的第一个块示例实际上是:
self.finishBlock = ^{
[[self image] setHidden:YES];
}
该块必须保留self
,以便它可以正确调用该image
方法。正如所写的那样,该块不能简单地保留image
,因为直到执行该块并image
调用该方法才获得图像。所以这里唯一的选择是保留self
.
在第二个区块中,您确实拥有:
self.finishBlock = ^{
self->_image.hidden = YES;
}
所以同样,self
必须保留,以便在_image
实际执行块时访问 ivar 的正确值。