iOS 内存优化

1. 把views设置为透明,透明的Views你应该设置它们的opaque属性为YES。

原因是这会使系统用一个最优的方式渲染这些views。这个简单的属性在IB或者代码里都可以设定。

Apple的文档对于为图片设置透明属性的描述是:

(opaque)这个属性给渲染系统提供了一个如何处理这个view的提示。如果设为YES,渲染系统就认为这个view是完全不透明的,这使得渲染系统优化一些渲染过程和提高性能。如果设置为NO,渲染系统正常地和其它内容组成这个View。默认值是YES。该属性为BOOL值,UIView的默认值是YES,但UIButton等子类的默认值都是NO.

在相对比较静止的画面中,设置这个属性不会有太大影响。然而当这个view嵌在scroll view里边,或者是一个复杂动画的一部分,不设置这个属性的话会在很大程度上影响app的性能。

你可以在模拟器中用Debug\Color Blended Layers选项来发现哪些view没有被设置为opaque。目标就是,能设为opaque的就全设为opaque!

2. 对于仅使用一次或是使用频率很低的大图片资源不要使用UIImage(named: "")而使用UIImage(contentsOfFile: "")

UIImage(named: "")返回的对象会保存在缓存中,只有退出程序才会释放内存;但下一次调用快,UIImage(contentsOfFile: "")返回的对象不会保存在缓存中,一旦对象销毁就会释放内存

3.一些图片本身非常适合用9片图的机制进行拉伸,但没有进行相应的优化

图片的内存占用是很大的,对于适合用9片图机制进行拉伸处理的图片,可以切出一个比实际尺寸小的多的图片,从而大量减少内存占用。我们可以利用Xcode的slicing功能,设定图片哪些部分不进行拉伸,哪些部分进行拉伸。在加载图片的时候,还是以正常的方式进行加载。

4.基于颜色创建纯色的图片时,尺寸过大

有时,我们需要基于颜色创建出UIImage,并用做UIButton在不同状态下的背景图片。由于是纯色的图片,那么,我们完全没有必要创建出和视图大小一样的图像,只需要创建出宽和高均为1px大小的图像就够了

5.在自定义的UIView子类中,利用drawRect:方法进行绘制改为CAShapeLayer

自定义drawRect会使APP消耗大量的内存,视图越大,消耗的越多。其消耗内存的计算公式为:
消耗内存 = (width * scale * height * scale * 4 / 1024 / 1024)MB

大部分情况下,绘制需求都可以通过CAShapeLayer实现,CAShapeLayer属于CoreAnimation框架,通过GPU来渲染图形,节省性能。动画渲染直接提交给手机GPU,不消耗内存

渲染快速。CAShapeLayer使用了硬件加速,绘制同一图形会比用Core Graphics快很多。

高效使用内存。一个CAShapeLayer不需要像普通CALayer一样创建一个寄宿图形,所以无论有多大,都不会占用太多的内存。

不会被图层边界剪裁掉。

不会出现像素化。

6.在Image Views中调整图片大小

如果要在UIImageView中显示一个来自bundle的图片,你尽量保证图片的大小和UIImageView的大小相同。在运行中缩放图片是很耗费资源的,特别是UIImageView嵌套在UIScrollView中的情况下。

如果图片是从远端服务加载的你不能控制图片大小,比如在下载前调整到合适大小的话,你可以在下载完成后,最好是用background thread,缩放一次,然后在UIImageView中使用缩放后的图片。

7.UILabel尺寸过大,为UILable设置背景色

如果一个UILabel的尺寸,大于ContentSize,那么会引起不必要的内存消耗。所以,在视图布局的时候,我们应该尽量使UILabel的尺寸等于其ContentSize

如果设置的背景色不是clearColor, whiteColor,会引起内存开销。可以将视图结构转变为UIView+UILabel,为UIView设定背景色,而UILabel只是用来显示文字,这样可以减少内存开销

8.高清大图片的处理,

网络下载高清大图片时,禁止解压

9.第三方库的缓存机制,适时缓存,适时清除

(1)Lottie动画框架

Lottie框架默认会缓存动画帧等信息,如果一个应用中使用动画的场合很多,那么随着时间的积累,就会存在大量的缓存信息。然而,有些缓存信息可能以后再也不会被用到了,例如闪屏页的动画引起的缓存。针对Lottie的缓存引起的内存占用,可以根据自己的意愿,选择如下两种处理办法:

1.禁止缓存 LRUAnimationCache.sharedCache.cacheSize = 0 缓存个数设置为零直接不缓存

2.适当的地方清除缓存 LRUAnimationCache.sharedCache.clearCache()

(2)图像缓存框架,如

SDWebImage的缓存机制,分为Disk和Memory两层,Memory这一层使得图片在被访问时可以免去文件IO过程,提高性能。默认情况下,Memory里存储的是解压后的图像数据,这个会导致巨大的内存开销。如果想要优化内存占用,可以选择存储压缩的图像数据,在应用启动的地方加如下代码

[SDImageCache sharedImageCache].config.shouldDecompressImages = NO;

[SDWebImageDownloader sharedDownloader].shouldDecompressImages = NO;

10.重用和延迟加载(lazy load) Views

更多的view意味着更多的渲染,也就是更多的CPU和内存消耗,对于那种嵌套了很多view在UIScrollView里边的app更是如此。

这里我们用到的技巧就是模仿UITableViewUICollectionView的操作:不要一次创建所有的subview,而是当需要时才创建,当它们完成了使命,把他们放进一个可重用的队列中。

这样的话你就只需要在滚动发生时创建你的views,避免了不划算的内存分配。

创建views的能效问题也适用于你app的其它方面。想象一下一个用户点击一个按钮的时候需要呈现一个view的场景。有两种实现方法:

1. 创建并隐藏这个view当这个screen加载的时候,当需要时显示它;

2. 当需要时才创建并展示。

每个方案都有其优缺点。用第一种方案的话因为你需要一开始就创建一个view并保持它直到不再使用,这就会更加消耗内存。然而这也会使你的app操作更敏感因为当用户点击按钮的时候它只需要改变一下这个view的可见性。

第二种方案则相反-消耗更少内存,但是会在点击按钮的时候比第一种稍显卡顿。

你可能感兴趣的:(iOS 内存优化)