强烈捕捉'自我'

时间:2013-10-09 13:43:28

标签: ios objective-c objective-c-blocks retain-cycle

我对一个按钮有以下操作,可以切换对象是显示为收藏还是非收藏:

- (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错误吗?两者都导致保留周期吗?

2 个答案:

答案 0 :(得分:3)

_favoriteButton是一个伊娃。它由您的类的特定实例拥有,因此使用它会捕获块中的当前selfReference 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修复第一个警告,则会在第二个块上发出警告。