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


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 不必带上后缀名,系统会自己根据名字去找


浅析 UIImage 的2种加载方式对内存的影响_第1张图片     浅析 UIImage 的2种加载方式对内存的影响_第2张图片


验证 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 = [UIImage imageNamed:@"backgound"];
    [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 = [UIImage imageNamed:imageName];
        [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 必须带上后缀名,以确保图片路径的完整性

浅析 UIImage 的2种加载方式对内存的影响_第3张图片     浅析 UIImage 的2种加载方式对内存的影响_第4张图片


验证 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 = [UIImage imageNamed:@"backgound"];
    [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 = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%02d",i+1] ofType:@"png"];
        UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
        [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: 方法后,图片占用的内存会自动释放掉,不会消耗内存。







你可能感兴趣的:(UI)