我对一个按钮有以下操作,可以切换对象是显示为收藏还是非收藏:
- (IBAction)addToFavorites:(UIButton *)sender {
if ([object isFavorite]) {
[_apiManager removeFromFavorite:[object ID] withCompletion:^ {
[_favoriteButton setImage:[UIImage imageNamed:@"favorite"] forState:UIControlStateNormal];
}];
}
else {
[_apiManager addToFavorite:[object ID] withCompletion:^ {
[_favoriteButton setImage:[UIImage imageNamed:@"favorite_yellow"] forState:UIControlStateNormal];
}];
}
}
两个完成块都相同,但图像名称除外。
XCode向else
案例发出警告:Capturing 'self' strongly in this block is likely to lead to a retain cycle
并指向_favoriteButton
。
但是,如果if
条件为真,则不会发生同样的情况。
我想这两种情况都不应该出现警告,我不明白为什么只有后者才能显示警告。这是一个Xcode错误吗?两者都导致保留周期吗?
答案 0 :(得分:3)
_favoriteButton
是一个伊娃。它由您的类的特定实例拥有,因此使用它会捕获块中的当前self
(Reference to instance variables inside a block)
相反,您应该创建一个对self的弱引用,并使用属性访问器,如下所示:
- (IBAction)addToFavorites:(UIButton *)sender {
__weak YourViewControllerClass *weakSelf = self;
if ([object isFavorite]) {
[_apiManager removeFromFavorite:[object ID] withCompletion:^ {
[weakSelf.favoriteButton setImage:[UIImage imageNamed:@"favorite"] forState:UIControlStateNormal];
}];
}
else {
[_apiManager addToFavorite:[object ID] withCompletion:^ {
[weakSelf.favoriteButton setImage:[UIImage imageNamed:@"favorite_yellow"] forState:UIControlStateNormal];
}];
}
}
答案 1 :(得分:0)
实际上,在这个例子中不清楚是否存在保留周期。如果将完成块声明为_apiManager
的属性,则会发生保留周期。如果它只是一个方法范围的块(只是方法参数),那么就没有保留周期,但XCode不够智能,无法检测到这些情况,并警告您可能存在保留周期。
关于你的问题,它只是关于命令,它警告你在第一个保留周期,第二个没关系,因为块已经从第一个块保留自己。如果使用__weak
self修复第一个警告,则会在第二个块上发出警告。