阻止并保留周期

时间:2012-07-11 08:40:58

标签: objective-c ios block

一个小问题:为什么Xcode会抱怨listing 1会导致保留周期,而listing 2却没有?在这两种情况下,_clients都是int实例变量。在listing 2中,0方法已为其分配了init

背景信息:我想在块中执行循环,只要至少有一个客户端从iPhone加速度计请求更新,我将发布到redis频道。如果没有剩余客户端,循环将退出并停止发布加速度计数据。

Listing 2来自我写的一个小测试应用,用于验证我的想法是否有效。 Listing 1已在实际项目中实施。

清单1

- (id)init {
  self = [super init];

  if (self) {
    _clients = 0;

    /**
     * The callback being executed
     */
    _callback = ^ {
      while (_clients > 0) { // Capturing 'self' strongly in this block is likely to lead to a retain cycle
        NSLog(@"Publish accelerometer data to redis (connected clients: %d)", _clients);
      }
    };
  }

  return self;
}

清单2

- (void)touchedConnectButton:(id)sender {
  _clients += 1;

  dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  dispatch_async(concurrentQueue, ^() {
    while(_clients > 0) {
      NSLog(@"Connected clients: %d", _clients);
    }
  });
}

2 个答案:

答案 0 :(得分:7)

在两个列表中,您指的是一个实例变量,因此隐式捕获自身。一个强大的自我。

这可以为您的问题提供第一个解决方案:

int clients = _clients;
// use `clients` instead of `_clients` in your blocks

或者,您可以使用弱自我:

id __weak weakself = self;
// use `weakself->_clients` in your blocks

你在列表1中得到错误的原因是因为块捕获self并且块存储在同一self的实例变量中,导致保留周期。上述两种解决方案都可以解决这个问题。

答案 1 :(得分:5)

清单1中有一个保留周期,因为在清单1中,self保留了ivar _callback,你可以在其中访问其他ivar,_clients,并且因为_clients是一个原始的var,所以块保留自己来访问它!

在清单2中,块由队列保留,而不是由self保留。

相关问题