块很可能会导致一个保留周期
我为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
它似乎工作正常,但当我打电话(如下面的代码片段所示),我得到一个警告:
区块很可能会导致保留周期
[_queue addAsynchronousOperationWithBlock:^(block signal) { [self foo:nil]; signal(); }];
foo
是使用这个类的类的一个方法。
与addOperationWithBlock:
相同的代码addOperationWithBlock:
来自NSOperationQueue
)不显示警告:
[_queue addOperationWithBlock:^ { [self foo:nil]; }];
我真的不明白这一点。 特别是我不明白的是,在两种情况下,我应该使用弱指针吗? 实际上这两个片段会带来保留周期,以防我不使用弱指针?
提炼其他人在这里写的:
- 这两个代码示例都不会创build一个持久的保留循环,这将会导致内存溢出。
- Xcode抱怨你的
addAsynchronousOperationWithBlock
方法,因为它有一个可疑的名字。 它不会抱怨addOperationWithBlock
因为它有关于addOperationWithBlock
特殊知识来覆盖它的怀疑。 - 要摆脱警告,请使用
__weak
(请参阅jszumski和matt的答案),或者将addAsynchronousOperationWithBlock
重命名为不以“add”或“set”开头。
为了详细阐述一下这些:
-
如果
self
拥有_queue
,那么将会有一个短暂的保留周期。self
会拥有自己的_queue
,它将拥有这些块,而调用[self foo:]
的块将拥有self
。 但一旦块完成运行,_queue
将释放它们,循环将被打破。 -
静态分析器已被编程为怀疑以“set”和“add”开头的方法名称。 这些名称表明,该方法可能会永久保留传递的块,可能会创build一个永久的保留周期。 因此警告你的方法。 它不会抱怨
-[NSOperationQueue addOperationWithBlock:]
因为知道NSOperationQueue
在运行后会释放阻塞的人不会被告知。 -
如果使用
__weak
则分析仪不会抱怨,因为不会有保留周期的可能性。 如果你重命名你的方法,分析器不会抱怨,因为它没有任何理由怀疑你的方法永久保留块传递给它。
当你在一个块中使用self
,它被块捕获,并可能导致一个保留周期。 当self
(或者有很强的参考意义)对这个块有很强的参考时,就会发生循环。 为了避免潜在的循环,请声明一个弱指针,然后在块中使用它:
YourClassName * __weak weakSelf = self; [_queue addAsynchronousOperationWithBlock:^(block signal) { [weakSelf foo:nil]; }];
jszumski的答案在本质上是正确的,但重要的是让“弱自我”舞蹈的forms正确。 forms(build立在他的代码上)是:
YourClassName * __weak weakSelf = self; [_queue addAsynchronousOperationWithBlock:^(block signal) { YourClassName * strongSelf = weakSelf; if (strongSelf) [weakSelf foo:nil]; }];
因此,我们通过一个强有力的参考来捕捉weakSelf
。 如果你不这样做, weakSelf
可以在你使用它的过程中不存在(因为你对它的引用很弱)。
看看我的书跳舞,还有其他的事情,你可以做的潜在的保留周期造成块:
http://www.apeth.com/iOSBook/ch12.html#_unusual_memory_management_situations
- ios中有多个单选button
- 指导UIScrollView和自动布局
- 如何在Swift 3中使用动画制作自定义AlertView / DialogBox
- iOS 10问题:即使设置了ContentSize,UIScrollView也不滚动
- Apple正在杀死白色标签的iOS应用! 我们应该做什么?
- 添加unit testing时的Mach-O链接器错误 – XCode
- Google SignIn SFSafariViewController / WebView在接受权限后redirect到Google.com
- 如何以编程方式在设备上使用CoreAudio在iOS下创build一定长度的空.m4a文件?
- 在Twitter App IOS上打开链接