您的位置:首页 > 产品设计 > UI/UE

浅析 UIImage 的2种加载方式对内存的影响

2015-12-29 12:18 567 查看
A、
UIImage的2种加载方式:


方式一:有缓存(图片所占用的内存会一直停留在程序中)

+ (nullable UIImage *)imageNamed:(NSString *)name;  // name是图片的文件名

解析:

1. 该方法会自动地做缓存,一般用于给控件添加素材图片,比如背景图片、placeHolder等。 

2. 使用( imageNamed:
)会使得占用的内存暴增,并占用内存,消耗内存。

方式二:无缓存(图片所占用的内存会在一些特定操作后被清除)

+ (nullable UIImage *)imageWithContentsOfFile:(NSString *)path;  
// path是图片的全路径

- (nullable instancetype)initWithContentsOfFile:(NSString *)path;  
 // path是图片的全路径

解析:

1. 该方法不会做缓存,如果该方法通过
path 能找到对应的文件名, 就返回这个文件的路径;如果找不到, 就返回nil;

2. 对于大量频繁使用的图片,使用( imageWithContentsOfFile: )方法,虽然内存也会增长很快,但使用完之后就会降下来,不会持续占用大量内存,造成内存的消耗。

B、
验证思路:


使用上面两个方法分别做 Demo 来验证,方法是通过 UIImageView 控件加载图片数组来播放一组动画,使得内存增长,查看结果是否占用内存。

C、
验证 TEST 1 : (imageNamed:)


把图片资源拷贝到 Assets.xcassets 文件夹下面,运行程序,会在 Bundle 文件夹下面生成 Assets.car 文件(见下图),该文件是经加密压缩之后产生的,里面存放的就是 Assets.xcassets 文件夹里的资源文件。Assets.xcassets 文件夹下面的图片文件只能使用( imageNamed:
方法获得。

注意:图片名 name 不必带上后缀名,系统会自己根据名字去找。


     


验证 Demo1:

#import "ViewController.h"
@interface ViewController ()
@property (nonatomic,strong) UIImageView *imageView;
@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
[self prepareTestAnimations];
}

-(void)prepareTestAnimations{

CGSize size = self.view.bounds.size;
CGFloat w = 262;
CGFloat h = 466;
CGFloat x = (size.width - w) / 2.0;
CGFloat y = (size.height - h) / 2.0 - 20;

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(x,y,w,h)];
imageView.image = <span style="color:#ff0000;">[UIImage imageNamed:@"backgound"]</span>;
[self.view addSubview:imageView];
self.imageView = imageView;
}

- (IBAction)buttonPress:(id)sender {
[self demo1];
}

-(void)demo1{

NSMutableArray *images = [NSMutableArray array];

for (int i = 0; i < 26; i++) {
NSString *imageName = [NSString stringWithFormat:@"%02d",i+1];
UIImage *image = <span style="color:#ff0000;">[UIImage imageNamed:imageName]</span>;
[images addObject:image];
}

CGFloat duration = 2;
self.imageView.animationImages = images;
self.imageView.animationDuration = duration;
self.imageView.animationRepeatCount = 1;
[self.imageView startAnimating];

[self.imageView performSelector:@selector(setAnimationImages:) withObject:nil afterDelay:duration];
}
使用 gif 图片展示:
结果验证:使用( imageNamed: )方法后,图片占用的内存并没有释放掉,占用内存,消耗内存。



D、
验证 TEST 2 (imageWithContentsOfFile:)




把图片 copy 到项目目录树中,可通过方法 ( [[NSBundle mainBundle] pathForResource: ofType:] )获得图片路径,通过 ( imageWithContentsOfFile: )获取到图片。运行程序,在
Bundle 文件夹下保存形式见下图。


注意:图片名 name 必须带上后缀名,以确保图片路径的完整性。


     


验证 Demo2:

#import "ViewController.h"
@interface ViewController ()
@property (nonatomic,strong) UIImageView *imageView;
@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
[self prepareTestAnimations];
}

-(void)prepareTestAnimations{

CGSize size = self.view.bounds.size;
CGFloat w = 262;
CGFloat h = 466;
CGFloat x = (size.width - w) / 2.0;
CGFloat y = (size.height - h) / 2.0 - 20;

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(x,y,w,h)];
imageView.image = <span style="color:#ff0000;">[UIImage imageNamed:@"backgound"]</span>;
[self.view addSubview:imageView];
self.imageView = imageView;
}

- (IBAction)buttonPress:(id)sender {
[self demo2];
}

-(void)demo2{

NSMutableArray *images = [NSMutableArray array];

for (int i = 0; i < 26; i++) {
NSString *imagePath = <span style="color:#ff0000;">[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%02d",i+1] ofType:@"png"]</span>;
UIImage *image = <span style="color:#ff0000;">[UIImage imageWithContentsOfFile:imagePath]</span>;
[images addObject:image];
}

CGFloat duration = 2;
self.imageView.animationImages = images;
self.imageView.animationDuration = duration;
self.imageView.animationRepeatCount = 1;
[self.imageView startAnimating];

[self.imageView performSelector:@selector(setAnimationImages:) withObject:nil afterDelay:duration];
}

使用 gif 图片展示:
结果验证:使用( imageWithContentsOfFile: )方法后,图片占用的内存会自动释放掉,不会消耗内存。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息