简体   繁体   English

阻止并保留周期

[英]Blocks and retain cycles

One minor question: why is Xcode complaining that listing 1 would lead to a retain cycle, while in listing 2 it does not? 一个小问题:为什么Xcode抱怨listing 1会导致保留周期,而在listing 2它不会? In both cases _clients is an int instance variable. 在这两种情况下, _clients都是一个int实例变量。 In listing 2 it is assigned 0 in the init method. listing 2它在init方法中被赋值为0

Background info: I would like to execute the loop in the block, as long as at least one client is requesting updates from the iPhone accelerometer, which I am publishing to a redis channel. 背景信息:我想在块中执行循环,只要至少有一个客户端从iPhone加速度计请求更新,我将发布到redis频道。 If there are no more clients left, the loop would quit and stop publishing accelerometer data. 如果没有剩余客户端,则循环将退出并停止发布加速计数据。

Listing 2 comes from a small test app I wrote to verify that my idea works. Listing 2来自我编写的一个小测试应用程序,用于验证我的想法是否有效。 Listing 1 is implemented in the real project. Listing 1在实际项目中实现。

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;
}

Listing 2 清单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);
    }
  });
}

In both listings, you are referring to an instance variable, thus implicitly capturing self. 在两个列表中,您指的是一个实例变量,因此隐式捕获自身。 A strong self. 一个强大的自我。

This leads to a first solution to your problem: 这导致您的问题的第一个解决方案:

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

Alternatively, you can use a weak self: 或者,您可以使用弱自我:

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

The reason why you got the error in listing 1 is because the block captures self and the block is stored in an instance variable of the same self, leading to a retain cycle. 你在列表1中得到错误的原因是因为块捕获self并且块存储在同一self的实例变量中,从而导致保留周期。 Both solutions above will solve that issue. 上述两种解决方案都将解决该问题。

There is a retain cycle in Listing 1 because in Listing1 self is retaining the ivar _callback in which you access an other ivar, _clients, and because _clients is a primitive var the block retains self to access it ! 清单1中有一个保留周期,因为在清单1中,self保留了ivar _callback,您可以在其中访问其他ivar,_clients,并且因为_clients是原始的var,所以块保留自己来访问它!

In Listing2, the block is retained by the queue and not by self. 在清单2中,块由队列保留,而不是由self保留。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM