一个小问题:为什么Xcode提示listing 1
会导致保留周期,而在listing 2
中却没有呢?在这两种情况下,_clients
都是int
实例变量。在listing 2
中,通过0
方法为其分配了init
。
背景信息:只要至少一个客户端从我发布到Redis channel 的iPhone加速度计请求更新,我想在代码块中执行循环。如果没有更多的客户端,则循环将退出并停止发布加速度计数据。Listing 2
来自我编写的一个小型测试应用程序,目的是验证我的想法是否有效。 Listing 1
在实际项目中实现。
list 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;
}
list 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);
}
});
}
最佳答案
在这两个 list 中,您都引用了一个实例变量,从而隐式捕获了self。坚强的自我。
这将导致您的问题的第一个解决方案:
int clients = _clients;
// use `clients` instead of `_clients` in your blocks
另外,您可以使用弱自我:
id __weak weakself = self;
// use `weakself->_clients` in your blocks
list 1中出现错误的原因是因为该块捕获了self,并且该块存储在同一个self的实例变量中,从而导致了保留周期。以上两种解决方案都可以解决该问题。
关于objective-c - 阻止并保留周期,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11428712/