博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS 中的 timer 任务(寻找内存恶鬼之旅)
阅读量:6037 次
发布时间:2019-06-20

本文共 1535 字,大约阅读时间需要 5 分钟。

前言

     在 iOS 的开发过程中定时任务中能找到使用的场景,然而在 iOS 中默认的有关 timerapi 总是那么晦涩难用,而且暗坑不断,一旦遇上,会让你一脸懵逼,为了不再同一个地方跌倒两次,我决心花些时间做一篇总结,也用以提醒读者,谨慎使用。      之前在做一个空白页的计时器的时候使用到了 CADisplayLink,这货把我坑惨了, 循环引用导致内存随着时间的增加而上升,短时间使用没啥感觉,要不是使用工具这是很难发现的。

分析

      通常,在解决循环引用的时候我们会引入 weak , 通过 weak 修饰打破循环引用中的 , 如:

@property (nonatomic, weak) CADisplayLink *link;    self.link = [CADisplayLink displayLinkWithTarget:self selector:@selector(fireAction)];    [self.link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];复制代码

然而,这样做 link 直接不工作了, 因为 link 没有别的地方引用,当它初始化完成立即就被释放掉了 。那么换一种思路呢?

__weak typeof(self) weakSelf = self;    self.link = [CADisplayLink displayLinkWithTarget:weakSelf selector:@selector(fireAction)];    [self.link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];复制代码

这样做也是徒劳的,当 self.link 持有 weakSelf 时也就是持有了 self, 而 link 是通过 target 强持有的 self 所以还是无法打破形成的环,我们通过 Memory Graph 就可以检测是否内存图关系:

这是
RunLoop
Timer 的内存关系,再看看
Timer
target 的关系:

方案

      既然这个环用常规的方法无法打破,那该怎么办呢? 这时候 NSProxy 就可也发挥它的长处了。我们实现一个 NSProxy 的子类 WeakProxyWeakProxy 弱引用一个 target ,然后在通过 WeakProxy 消息转发到 target 从而达到破除循环的效果:

- (id)forwardingTargetForSelector:(SEL)selector {    return _target;}- (void)forwardInvocation:(NSInvocation *)invocation {    void *null = NULL;    [invocation setReturnValue:&null];}- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {    return [NSObject instanceMethodSignatureForSelector:@selector(init)];}复制代码

proxy 弱引用的 target 所以不影响 target 的正常释放,当 target 释放后,link 引用计数减一 link 释放,proxy 引用计数减一也会释放,因此,原来的环不在了,完美解决了相互引用的问题。

转载地址:http://dilhx.baihongyu.com/

你可能感兴趣的文章
ELCSlider
查看>>
XCode工程中 Targets详解
查看>>
Ext.Msg.prompt的高级应用
查看>>
Postgres 中 to_char 格式化记录
查看>>
关于联合索引
查看>>
开源 java CMS - FreeCMS2.7 登录移动端管理中心
查看>>
Android FM模块学习之三 FM手动调频
查看>>
Python 设置系统默认编码以及其他编码问题大全
查看>>
keyboard rock
查看>>
Java几款性能分析工具的对比
查看>>
openfire smack包
查看>>
Storm-0.10.0集群安装(一)
查看>>
phpwind or discuz做论坛好点呢
查看>>
JavaScript基础(五)函数
查看>>
.NET委托解析(异步委托)
查看>>
php防注入
查看>>
1.1 Linux常用命令
查看>>
关于thinkpad和thinkpad x230更换固态硬盘后蓝屏0x000000f4或0x0000007a错误
查看>>
Windows Azure体验之配置点到站点×××连接
查看>>
转:java 注解 实战剖析
查看>>