关于 UIImage 以及 YYImage 的内存问题与解决方案

本文探讨UIImage的内存处理,包括Resource和ImageAssets的优缺点,以及YYImage如何解决内存问题。Resource适合大图管理,避免内存浪费,而ImageAssets适合小图复用,减少沙盒读取。YYImage模仿imageNamed实现,但可能导致内存占用增加。解决方案包括使用MRC+字典或弱引用字典来平衡内存管理和对象销毁。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这篇文章是笔者在开发App过程中发现的一些内存问题, 然后学习了YYKit框架时候也发现了图片的缓存处理的不够得当. 以下内容是笔者在开发中做了一些实验以及总结. 如有错误望即时提出, 笔者会第一时间改正.

文章的前篇主要是对两种不同的UIImage工厂方法的分析, 以及对 YYKit 中的 YYImage 的分析. 罗列出这些工厂方法的内存管理的优缺点.

文章的后篇是本文要说明的重点, 如何结合两种工厂方法的优点做更进一步的节约内存的管理.

PS

本文所说的 Resource 是指使用imageWithContentsOfFile:创建图片的图片管理方式.

ImageAssets 是指使用imageNamed:创建图片的图片管理方式.

如果你对这两个方法已经了如指掌, 可以直接看UIImage 与 YYImage 的内存问题和后面的内容

UIImage 的内存处理

在实际的苹果App开发中, 将图片文件导入到工程中无非使用两种方式. 一种是 Resource (我也不知道应该称呼什么,就这么叫吧),还有一种是 ImageAssets 形式存储在一个图片资源管理文件中. 这两种方式都可以存储任何形式的图片文件, 但是都有各自的优缺点在内. 接下来我们就来谈谈这两种图片数据管理方式的优缺点.

Resource 与 “imageWithContentsOfFile:”

Resource 的使用方式

将文件直接拖入到工程目录下, 并告诉Xcode打包项目时候把这些图片文件打包进去. 这样在应用的”.app”文件夹中就有这些图片. 在项目中, 读取这些图片可以通过以下方式来获取图片文件并封装成UIImge对象:

NSString *path = [NSBundle.mainBundle pathForResource:@"image@2x" type:@"png"];
UIImage *image = [UIImage imageWithContentsOfFile:path];

而底层的实现原理近似是:

+ (instancetype)imageWithContentsOfFile:(NSString *)fileName {
    NSUInteger scale = 0;
    {
        scale = 2;//这一部分是取 fileName 中"@"符号后面那个数字, 如果不存在则为1, 这一部分的逻辑省略
    }
    return [[self alloc] initWithData:[NSData dataWithContentsOfFile:fileName scale:scale];
}

这种方式有一个局限性, 就是图片文件必须在.ipa的根目录下或者在沙盒中. 在.ipa的根目录下创建图片文件仅仅只有一种方式, 就是通过 Xcode 把图片文件直接拖入工程中. 还有一种情况也会创建图片文件, 就是当工程支持低版本的 iOS 系统时, 低版本的iOS系统并不支持 ImageAssets 打包文件的图片读取, 所以 Xcode 在编译时候会自动地将 ImageAssets 中的图片复制一份到根目录中. 此时也可以使用这个方法创建图片.

Resource 的特性

在 Resource 的图片管理方式中, 所有的图片创建都是通过读取文件数据得到的, 读取一次文件数据就会产生一次NSData以及产生一个UIImage, 当图片创建好后销毁对应的NSData, 当UIImage的引用计数器变为0的时候自动销毁UIImage. 这样的话就可以保证图片不会长期地存在在内存中.

Resource 的常用情景

由于这种方法的特性, 所以 Resource 的方法一般用在图片数据很大, 图片一般不需要多次使用的情况. 比如说引导页背景(图片全屏, 有时候运行APP会显示, 有时候根本就用不到).

Resource 的优点

图片的生命周期可以得到管理无疑是 Resource 最大的优点, 当我们需要图片的时候就创建一个, 当我们不需要这个图片的时候就让他销毁. 图片不会长期的保存在内存当中, 所以不会有很多的内存浪费. 同时, 大图一般不会长期使用, 而且大图占用内存一般比小图多了好多倍, 所以在减少大图的内存占用中, Resource 做的非常好.

ImageAssets 与 “imageNamed:”

ImageAssets 的设计初衷主要是为了自动适配 Retina 屏幕和非 Retina 屏幕, 也就是解决 iPhone 4 和 iPhone 3GS 以及以前机型的屏幕适配问题. 现在 iPhone 3GS 以及之前的机型都已被淘汰, 非 Retina 屏幕已不再是开发考虑的范围. 但是 plus 机型的推出将 Retina 屏幕又提高了一个水平, ImageAssets 现在的主要功能则是区分 plus 屏幕和非 plus 屏幕, 也就是解决 2 倍 Retina 屏幕和 3 倍 Retina 屏幕的视屏问题.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值