Ios 块很可能导致一个保留周期
我为Ios 块很可能导致一个保留周期,ios,objective-c,objective-c-blocks,nsoperationqueue,Ios,Objective C,Objective C Blocks,Nsoperationqueue,我为NSOperationBlock @implementation NSOperationQueue (Extensions) -(void)addAsynchronousOperationWithBlock:(void (^)(block))operationBlock { dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); block signal = ^ { dispatch_s
NSOperationBlock
@implementation NSOperationQueue (Extensions)
-(void)addAsynchronousOperationWithBlock:(void (^)(block))operationBlock
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
block signal = ^ {
dispatch_semaphore_signal(semaphore);
};
[self addOperationWithBlock:^{
operationBlock(signal);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_release(semaphore);
}];
}
@end
它似乎工作正常,但当我调用它时(如以下代码段所示),我得到一个警告:
块很可能导致一个保留周期
foo
是使用此类别的类的方法
与addOperationWithBlock:
(来自NSOperationQueue
)相同的代码不显示警告:
[_queue addOperationWithBlock:^ {
[self foo:nil];
}];
我真的不明白。
特别是我不明白的是:
我应该在这两种情况下都使用弱指针吗?在我不使用弱指针的情况下,这两个代码段是否会进入一个保留周期 在块内使用
self
时,它会被块捕获,并可能导致保留周期。当self
(或其具有强引用的对象)具有对块的强引用时,发生循环。为避免潜在循环,请声明弱指针并在块中使用该指针:
YourClassName * __weak weakSelf = self;
[_queue addAsynchronousOperationWithBlock:^(block signal) {
[weakSelf foo:nil];
}];
jszumski的回答本质上是正确的,但重要的是要让“弱自我”舞蹈的形式正确。表格(基于他的代码)为: 因此,我们通过一个强引用来捕获
weakSelf
。如果你不这样做,<代码>弱自我>代码>当你在使用它的时候,它就会消失(因为你对它的引用很弱)。
请参阅我的《舞蹈》一书,以及您可以对由块引起的潜在保留周期所做的其他事情:
要提取其他人在此处所写的内容:
addAsynchronousOperationWithBlock
方法有可疑名称。它不会抱怨addOperationWithBlock
,因为它对addOperationWithBlock
有专门的了解,可以消除它的怀疑\uu-weak
(请参阅jszumski和matt的答案)或重命名addAsynchronousOperationWithBlock
以不以“add”或“set”开头self
拥有\u队列
,您将有一个短暂的保留周期self
将拥有\u queue
,它将拥有块,而调用[self foo:
的块将拥有self
。但一旦这些块完成运行,\u queue
将释放它们,循环将被打破-[NSOperationQueue addOperationWithBlock:
,因为知道NSOperationQueue
在运行块后释放块的人告诉它不要这样做\uuuu-weak
分析仪不会抱怨,因为不可能出现保留周期。如果重命名方法,分析器不会抱怨,因为它没有任何理由怀疑您的方法永久保留传递给它的块具体来说,如果区块为self所有,甚至是间接拥有。否则就可以了。很好,我更新了答案,使之更明确。好吧,但是为什么我对addOperationWithBlock没有同样的问题呢?这里是块的强引用在哪里?但是代码片段都捕获了自身。分析器在一种情况下抱怨,而在另一种情况下却没有抱怨,原因是一些方法名称硬编码到分析器中,请参阅我对上述问题的评论。还要注意,捕获self通常并不坏-它可以用来保持对象的活动状态,直到调用块为止,compare.compare:
Sema::checkRetainCycles()
在静态分析器中,如果方法名称以“set”或“add”开头,而不是“addAsynchronousOperationWithBlock”开头,则会发出警告。。。。更正:如果方法名称以“set”或“add”开头,静态分析器会发出警告,但不是针对“addOperationWithBlock”。我假设您在上一个代码示例中指的是“addOperationWithBlock”而不是“addAsynchronousOperationWithBlock”?我更改了问题以使其更清楚\u queue==self,因此self保留block,block reserves self==\u queue ERGO a cycleI也将始终使用此模式,但实际上,如果仅使用[weakSelf foo:nil],则无法释放对象代码>,比较:通过objc_loadWeak()
访问块中的weakSelf
,它会保留并自动删除对象。谢谢您的回答,也谢谢您的链接。我在读它的时候学到了很多。我仍然对我的问题有一些疑问,我编辑了这些问题来表达我的谢意。现在我明白了。
YourClassName * __weak weakSelf = self;
[_queue addAsynchronousOperationWithBlock:^(block signal) {
[weakSelf foo:nil];
}];
YourClassName * __weak weakSelf = self;
[_queue addAsynchronousOperationWithBlock:^(block signal) {
YourClassName * strongSelf = weakSelf;
if (strongSelf)
[weakSelf foo:nil];
}];