6

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

背景信息:我想在块中执行循环,只要至少有一个客户端从 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);
    }
  });
}
4

2 回答 2

7

在这两个清单中,您指的是一个实例变量,因此隐含地捕获了 self. 一个坚强的自己。

这导致您的问题的第一个解决方案:

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

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

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

清单 1 中出现错误的原因是该块捕获了 self 并且该块存储在同一个 self 的实例变量中,从而导致了一个保留循环。上述两种解决方案都可以解决该问题。

于 2012-07-11T08:50:00.973 回答
5

清单 1 中有一个保留循环,因为在清单 1 中 self 保留了 ivar _callback,您可以在其中访问另一个 ivar,_clients,并且因为 _clients 是一个原始 var,所以块保留 self 来访问它!

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

于 2012-07-11T08:49:17.697 回答