Closed
Description
YYKit的代码: (YYDiskCache.m)
- (void)_trimInBackground {
__weak typeof(self) _self = self;
dispatch_async(_queue, ^{
__strong typeof(_self) self = _self;
if (!self) return;
dispatch_semaphore_wait(self->_lock, DISPATCH_TIME_FOREVER);
[self _trimToCost:self.costLimit];
[self _trimToCount:self.countLimit];
[self _trimToAge:self.ageLimit];
[self _trimToFreeDiskSpace:self.freeDiskSpaceLimit];
dispatch_semaphore_signal(self->_lock);
});
}
看下dispatch_async官方文档说明:
- @param block
- The block to submit to the target dispatch queue. This function performs
- Block_copy() and Block_release() on behalf of callers.
- The result of passing NULL in this parameter is undefined.
block参数系统会自动调用copy,保证self不被释放,在block执行结束后会release。所以没必要传__weak self。 如果传__weak self,就无法保证block在执行时,self是否被释放,反而会出现错误。所以不能传__weak self。
Activity
ibireme commentedon Dec 10, 2015
你可能需要再多了解一下 block、weak、strong 相关的内存管理。
在①处,block 会捕获到 _self,这个值是 weak 的,随后在 block 执行①时,这个 __weak _self 会被赋值为 __strong self。在②处,如果 weak self 已经被释放,那么这里就会直接返回。这么做能避免循环引用,并且能确保在使用 self 时其不会被释放。
如果你用过 ReactiveCocoa,或者写过一些常见的一些网络库的 block 回调,应该会对这种写法很熟悉。
diong commentedon Dec 10, 2015
我想说的是,dispatch_async这个方法里面,有没有必要传__weak self进来?
一些网络库的block回调有这样写法,是因为block和调用的对象双反互相强引用,会出现循环引用,才用__weak self来避免。 dispatch_async与self之间又不会引起循环引用,所以觉得没必要传__weak self.
ibireme commentedon Dec 11, 2015
self->_queue->block->self 这不是循环引用吗
Mryong commentedon Jun 8, 2016
如果self->_queue->block->self 是循环引用,那么self->_queue->block->strongSelf 难道就不是循环引用了么?所以这句话__strong typeof(_self) self = _self; 有什么意义呢?
Mryong commentedon Jun 8, 2016
(void)_trimRecursively {
__weak typeof(self) _self = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_autoTrimInterval * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
__strong typeof(_self) self = _self;
if (!self) return;
[self _trimInBackground]; [
self _trimRecursively]; });
}
首先我觉得
__weak typeof(self) _self = self;
__strong typeof(_self) self = _self;
这两句没必要写,先weak再strong 和原来的self有什么区别呢? 原来的self指针就是strong类型啊。
其次我觉得 if (!self) return 这个条件永远不会成立,因为这时候已经定了strongSelf强指针指向self对象,所以self的对象的引用计数必然已经+1了,直到block释放的时候才会-1,而此时显然blokc还没释放,所以self指向的对象的应用计数必然大于等于1,所以不会释放,所以!self条件必然不会成立。
duxinxiao commentedon Aug 2, 2016
官方文档上说会Block_copy() 和Block_release() ,所以会帮你打破引用循环,不用weak/strong应该也没问题
song-react commentedon Jun 6, 2017
@Mryong ②那里有处理,所以没问题的
相当于
Norcy commentedon Oct 31, 2017
GCD的应该不需要用 weakSelf。
_queue不会持有 block。
JohnDn commentedon Apr 2, 2018
我认为使用weakSelf时,当这个viewController释放了,weakSelf会变成nil。
但是如果使用self,self会在Block释放时,才释放,应该不会造成循环引用。
tomscheney commentedon Apr 2, 2018
JohnDn commentedon Apr 2, 2018
@tomschenjian 刚才可能没说清楚,我那段话里Block指的是dispatch_async block,这里只针对GCD中使用self进行讨论。当然一般情况里,self持有block,block中也强引用self,这样确实是强引用循环,block的释放需要依赖self的释放,同时self的释放也依赖block的释放。
但是在dispatch_async block回调中强引用了self,不会造成循环引用吧?dispatch_async block结束后会自动release,同时dispatch_async block对self的强引用也结束了,self也会释放。
还请大神多多指教。。。
tomscheney commentedon Apr 2, 2018
hssdx commentedon Apr 2, 2018
@Mryong 你没理解什么是循环引用,那里的 strongSelf 是在 {...} 代码块内部的临时变量!临时变量在代码块退出时会自动调用 release
song-react commentedon Apr 3, 2018
不用争了, self->queue -> async block -> weak self
如果是Queue.main, queue.global 就不需要
8 remaining items