一、加载方式
+ (nullable UIImage *)imageNamed:(NSString *)name;
+ (nullable UIImage *)imageWithContentsOfFile:(NSString *)path;/- (nullable instancetype)initWithContentsOfFile:(NSString *)path;/+ (nullable UIImage *)imageWithData:(NSData *)data;/- (nullable instancetype)initWithData:(NSData *)data;
二、加载过程:
用imageNamed的方式加载时,系统会把图像Cache到内存。如果图像比较大,或者图像比较多,用这种方式会消耗很大的内存,而且释放图像的内存是一件相对来说比较麻烦的事情。
+ (nullable UIImage *)imageNamed:(NSString *)name;
这个方法用一个指定的名字在系统缓存中查找并返回一个图片对象如果它存在的话。
如果缓存中没有找到相应的图片,这个方法从指定的文档中加载然后缓存并返回这个对象,通常是加载bundle中的图片资源!因此+ (nullable UIImage *)imageNamed:(NSString *)name;
的优点是当加载时会缓存图片。所以当图片会频繁的重复使用时,那么用+ (nullable UIImage *)imageNamed:(NSString *)name;
的方法会比较好。
三、使用场景:
例如:如果利用imageNamed的方式加载图像到一个动态数组NSMutableArray,然后将将数组赋予一 个UIView的对象的animationImages进行逐帧动画,那么这将会很有可能造成内存泄露,并且释放图像所占据的内存也不会那么简单。
但是利用imageNamed加载图像也有自己的优势。对于同一个图像系统只会把它Cache到内存一次,如果是第二次调用,它不是从文件中取,而是直接从缓存中拿,也就是说读的不同的图片越多内存会越来越大,但是直接从内存中取图片,速度肯定快一点,性能高一点。so这对于图像的重复利用是非常有优势的。
例如:你需要在一个TableView里重复加载同样一个图标,那么用imageNamed加载图像,系统会把那个图标Cache到内存,在Table里每次利用那个图像的时候,只会把图片指针指向同一块内存。这种情况使用imageNamed加载图像就会变得非常有效。
利用NSData或imageWithContentOfFile方式加载时,图像会被系统以数据方式加载到程序。当你不需要重用该图像,或者你需要将图像以数据方式存储到数据库,又或者你要通过网络下载一个很大的图像时,请尽量使用imageWithData的方式加载图像,仅仅加载图片而不在内存中缓存下来,那么每次获取时都会重新去加载。
无论用哪种方式加载图像,图像使用结束后,一定要记得显示释放内存(MRC下)。
两种方式各有利弊,imageNamed性能高一点,但是前提是图片占用的内存较小,且该图被多个地方或频繁使用,但是如果,图片存储空间大,内存吃不消,就用
+ (nullable UIImage *)imageWithContentsOfFile:(NSString *)path;
- (nullable instancetype)initWithContentsOfFile:(NSString *)path;
+ (nullable UIImage *)imageWithData:(NSData *)data;
- (nullable instancetype)initWithData:(NSData *)data;
从路径加载图片。
-imageNamed:
是读取到内存后会缓存下来,下次再读取时直接从缓存中获取,因此访问效率要比较高。对于图片资源比较小,使用比较频繁的图片,通常会选择使用此种方式来加载。当然,若不需要考虑性能时,直接使用此种方式也是可以的。
-initWithContentsOfFile:
当图片资源比较大,或者图片资源只使用一次就不再使用了,那么使用此种方式是最佳方式。当应用程序需要加载一张比较大的图片并且是一次性使用的,那么是没有必要去缓存这个图片的,用-imageWithContentsOfFile:
是最为经济的方式,这样不会因为UIImage元素较多情况下,CPU会被逐个分散在不必要的缓存上而浪费过多CPU时间。另外,当我们的图片不是PNG图片时,我们通常会选择此种方式来加载。
四、代码使用:
UIImage *image = [UIImageimageNamed:@"logo"];
// 在开发中,通常都定义了快捷调用的宏
#define kImgName(name) [UIImage imageNamed:name]
// 使用时就更简化了
UIImage *image = kImgName(@"logo");
NSString *filePath = [[NSBundle mainBundle]pathForResource:@"logo"ofType:@"png"];
UIImage *image = [[UIImage alloc]initWithContentsOfFile:filePath];
// 定义成宏,简化调用
#define kResourcePath(name, type) ([[NSBundle mainBundle] pathForResource:name ofType:type])
#define kImgFromFile(name, type) [[UIImage alloc] initWithContentsOfFile:kResourcePath(name, type)]
// 调用也变得很简化了
UIImage *image = kImgFromFile(@"logo", @"png");
注意:
图片格式及NSBundle加载全路径:
1.xcode或者说苹果官方是极力推荐使用的图片格式是png
2.所有如果项目中用得是png的图片,则不用写后缀名
3.其他格式要求后缀名,特别是用UIImage加载图片时
五、摘录
1.加载Assets.xcassets这里面的图片:
1. 打包后变成Assets.car
2. 拿不到路径
3. 只能通过imageNamed:来加载图片
4. 不能通过imageWithContentsOfFile:来加载图片
2.放到bundle 中的图片:
1. 可以拿到路径
2. 能通过imageNamed:来加载图片
3. 也能通过imageWithContentsOfFile:来加载图片
3. imageNamed:
1.就算指向它的指针被销毁,该资源也不会被从内存中干掉
2.放到Assets.xcassets的图片,默认就有缓存
3.图片经常被使用 (需要缓存)
4. imageWithContentsOfFile:
1.指向它的指针被销毁,该资源会被从内存中干掉
2.放到项目中的图片就不带有缓存
3.不经常用,大批量的图片