2020-03-12 App运行时内存飙升的两种情况

在开发中,我们常常遇到内存飙升的情况,常见的分析方法是使用苹果调试工具Instruction
它的进入路径是 Xcode —— product —— profile ——选择Allocations

image.png

点击红点,自动运行模拟器。
操作模拟器,跟踪内存变化。

当发现内存提升后,无法下降时,点击暂停
分析内存产生位置:调用栈,如下所示界面


调用栈

到此,我们会遇到两个问题:
1.定位到的代码是自己写的代码
2.定位到的代码是系统的代码

第一种情况,我遇到过,我来讲讲我的个人经历:
这是我一段修改后的别人代码。在tableViewcell里面,每个data赋值的时候,代码里都make 一个masonry的约束。
那么在滑动时,多次赋值,多次创建出更多约束。

千万不要以为masnory约束不占内存。

实际上,多次make重复的约束,不仅会让内存提高,还会导致约束计算过程复杂化,也会更加地耗时。
将约束代码移到cell创建的地方,内存飙升消失。

第二种情况,我也遇到过。
说实话,我一开始真的不知道怎么去定位这个问题。全是系统的方法,根本不是用户代码,那该如何定位呢?
这种情况,其实是你调用了不好的系统Api。而这些系统Api有个相同的毛病:

这些系统Api会导致App在运行时内存飙升。强烈不建议重复使用。

如果你使用循环或者反复调用,内存一定会快速升高,导致程序崩溃。
那我们改如何定位这些代码的位置呢?
我们试一试笨方法:单步调试+联想猜测

其实单步调试很不准确,它可能把临时变量带来的内存提升给捕捉到,这时候需要开发者去仔细甄别这部分代码的区别了。

我当时卡在系统方法:image_PNG_Data 和Data_XXX_disk这些方法上了。首先这些系统方法会占用10M或者30M的内存空间,除此之外,反复创建这些内存,内存轻松升到了100多M。
我猜测是cell中图片复制方法 imageWithData导致的。
我查了资料,它不是从内存读取图片,而是直接从disk硬盘中读取图片。
而我又要显示多张图片,这样就导致多个disk读取IO对象的存在,他们少则10M,大的30M,所以问题就严重了。
类似这种的方法还有:imageContentWithUrl的方法。

解决方案:
第一次时读取data并为图片,将图片使用UIIMageGraph重新绘制,生成一个很小但是够用可以用来显示的小图片,强引用这张小图片,以后在调用,直接使用存在内存中的小图片。
这样,我的一个tableView页面最多同时显示10个cell时,内存不会超过45M。

你可能感兴趣的:(2020-03-12 App运行时内存飙升的两种情况)