从iOS的内存管理思考学习的深度

Posted by syea on May 24, 2018

从iOS的内存管理思考学习的深度

菜鸡瞎写

刚入门写 iOS 的时候,根本不会考虑什么内存管理,结果后来经常收到内存警告。

发现问题

把收到的内存警告放到网上一搜,蹭蹭蹭出来很多内存管理相关的内容,发现了应该是自己写的代码有问题,产生了内存泄露。

解决问题

那么怎么解决呢,继续搜”如何解决 iOS 内存泄露”,唰唰唰出来一堆解决方案。基本上都是循环引用,大概率出现在 block 的使用上,只要在 block 前 __weak __typeof(self) weakSelf = self; ,block 内 __strong typeof(weakSelf) strongSelf = weakSelf;就可以完美解决。

修改项目

逐个查找项目中的 block,每个都写上 __weak,__strong

Over.

没错,这就是以前我学习的深度。

成长

后来在种种因素下,我又学习了很多。

  • 遇到的问题越来越多
    1.写一个图片轮播器的时候用到了 NSTimer,也产生了内存泄漏。
      self.timer = [NSTimer timerWithTimeInterval:_timeInterval target:self selector:@selector(updateTimer) userInfo:nil repeats:YES];
      [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
    

    要记得把 timer invalidate.到这里其实已经解决问题了,但是有时候,可能我们掌握不好invalidate的时机。那该怎么解决呢?
    NSProxy
    原先:self 持有了 timer,timer 又将 self 作为 target。产生了循环引用。
    现在:我们将 timer 的 target 设为 NSProxy,通过 NSProxy 将消息转发至 self,此处 NSProxy 弱引用 self,避开了循环引用。

    2.遇到Core Foundation对象的时候,ARC写惯了,根本没想过去释放它,也内存泄漏了。
    牢记这些对象使用过后要调用CFRelease!

  • 想知道的更全面
    遇到一个内存泄露的问题,解决一个。这样下去也不是办法,干脆就去了解下,iOS 下到底有哪些方式会造成内存泄漏。
    查阅了一些资料,发现还有
    1. delegate 要用 weak 关键字。
    2. 纯粹的两个对象互相引用,a.obj = b; b.obj = a;
    3. 单例持有的 block,持有了当前控制器或者其他已经拥有强引用的对象。 …

  • 想规避的更彻底
    靠自身的功底,在编码过程中时刻记得规避内存泄漏固然是最佳方式,但是人总有犯错的时候,尤其有些错误隐藏的很深。这个时候就应该想想,有什么工具可以帮助我们检测项目中有内存泄漏的地方。
    1. instruments - Link, Xcode 内置的内存泄漏检测工具。
    2. MLeaksFinder 等第三方库。

  • 想理解得更透彻
    那么 iOS 到底是怎么管理内存的呢?为什么还会有循环引用这种事情要程序员去管理?
    总结一下就是靠 引用计数。当一个对象的引用计数为0时,这个对象就会被释放。或者说当一个对象没有强引用指针指向它时就被释放。当两个对象互相用强指针指着的时候,引用计数都不为0,也就没办法释放了。另一方面,也说明了不是所有的 block 都需要__weak,__strong来一下,要想清楚是否真的产生了循环引用。

  • 面试的时候被问懵
    几乎每次面试都会问内存管理,有一次回答完使用__weak,__strong来规避循环引用。面试官问,那么__weak,__strong都做了哪些事情呢?
    有点小崩..
    推荐阅读:iOS 底层解析weak的实现原理

    __weak,__strong就一定能保证安全吗?
    emmmmm..
    推荐阅读:Weak-Strong-Dance真的安全吗?

    那么你在开发过程中做过哪些内存优化或者性能优化方面的事情呢🙃?
    平时优化内存的文章看了不少,但是大多都是一些小 tip,cell 重用、懒加载、避免layer离屏渲染、较少出现的图片或者大图不使用imageNamed使用imageWithContentsOfFile……
    有什么厉害一点的操作吗?没有。
    推荐阅读:iOS 保持界面流畅的技巧

思考

我们学一门技术到底要学的多深呢?

一开始我以为是兴趣使然,喜欢底层就往深的去看,喜欢做产品可以浅尝辄止。

然而不深入真的能做好一款产品吗?

就举例我们做一款 App:

  1. 做好内存管理,不会用着用着就内存爆炸
  2. 做好所有机型/版本号的适配,至少界面看起来不能有问题吧
  3. 写每个方法都做好异常处理,不能动不动数组越界,空指针异常
  4. 便于扩展,虽然扩展这块仁者见仁智者见智,想太多容易多度设计,但是想的少就等着修修补补或者返工重做吧 …

不学深可以做出产品吗,肯定没问题,就像我刚毕业那会做的产品,全是坑😑。

所以,一切都跟自己的追求有关

想做的更好,自然会学的更深。

扩展一下

其实关于 iOS 的内存管理还能讲很多,比如我们讲到可以用一些第三方库检测内存泄露,那么他们的原理是什么,具体又是怎么实现的? 然后我们还可以了解一下其他语言是怎么管理内存的,各有哪些优缺点,像 java 就不需要考虑循环引用。当然自己也还有很多没有掌握,继续加油。