内存优化工具
Instruments的Allocations
这个工具能显示出应用的实际内存占用,并可以按大小进行排序。我们只要找出那些占用高的,分析其原因,找到相应的解决办法。
Xcode的Memory Graph
这款工具在查找内存泄漏方面,可以作为MLeaksFinder的补充,用于分析对象之间的循环引用关系。
另外通过分析某个时刻的Live Objects,可以分析出哪些是不合理的。
常见内存占用高的原因
使用了不合理的API
网络下载的图片过大
第三方库的缓存机制
Masonry布局框架
没必要常驻内存的对象,实现为常驻内存
数据模型中冗余的字段
内存泄漏
1.使用了不合理的API
1.1 对于仅使用一次或是使用频率很低的大图片资源,使用了[UIImage imageNamed:]方法进行加载
图片的加载,有两种方式,一种是[UIImage imageNamed:],加载后系统会进行缓存,且没有API能够进行清理;另一种是[UIImage imageWithContentsOfFile:]或[[UIImage alloc] initWithContentsOfFile:],系统不会进行缓存处理,当图片没有再被引用时,其占用的内存会被彻底释放掉。
基于以上特点,对于仅使用一次或是使用频率很低的大图片资源,应该使用后者。使用后者时,要注意图片不能放到Assets中。
1.2 一些图片本身非常适合用9片图的机制进行拉伸,但没有进行相应的优化
图片的内存占用是很大的,对于适合用9片图机制进行拉伸处理的图片,可以切出一个比实际尺寸小的多的图片,从而大量减少内存占用。比如下面的图片:
image.png
左右两条竖线之间的部分是纯色,那么设计在切图时,对于这部分只要切出来很小就可以了。然后我们可以利用Xcode的slicing功能,设定图片哪些部分不进行拉伸,哪些部分进行拉伸。在加载图片的时候,还是以正常的方式进行加载。
1.3在没有必要的情况下,使用了-[UIColor colorWithPatternImage:]这个方法
项目中有代码使用了UILabel,将label的背景色设定为一个图片。为了将图片转为颜色,使用了上述方法。这个方法会引用到一个加载到内存中的图片,然后又会在内存中创建出另一个图像,而图像的内存占用是很大的。
解决办法:此种场景下,合理的是使用UIButton,将图片设定为背景图。虽然使用UIButton会比UILabel多生成两个视图,但相比起图像的内存占用,还是完全值得的。
1.4 在没有必要的情况下,使用Core Graphics API,修改一个UIImage对象的颜色
使用此API,会导致在内存中额外生成一个图像,内存占用很大。合理的做法是:
设定UIView的tintColor属性
将图片以UIImageRenderingModeAlwaysTemplate的方式进行加载
代码示例:
view.tintColor = theColor;
UIImage *image = [[UIImage imageNamed:name] imageWithRenderingMode: UIImageRenderingModeAlwaysTemplate]
1.5 基于颜色创建纯色的图片时,尺寸过大
有时,我们需要基于颜色创建出UIImage,并用做UIButton在不同状态下的背景图片。由于是纯色的图片,那么,我们完全没有必要创建出和视图大小一样的图像,只需要创建出宽和高均为1px大小的图像就够了。
代码示例:
//外部应该调用此方法,创建出1px宽高的小图像
+ (UIImage*)createImageWithColor:(UIColor *)color {