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

本文详细分析了UIImage的imageNamed:和imageWithContentsOfFile:两种加载图片方式对内存的影响。imageNamed:会自动缓存,适合用于静态素材,但可能导致内存持续占用;而imageWithContentsOfFile:不缓存,适用于大量频繁使用的图片,使用后内存会下降,避免内存消耗。实验证明,imageNamed:加载的图片内存不会释放,而imageWithContentsOfFile:则能自动释放内存。

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


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: 方法后,图片占用的内存会自动释放掉,不会消耗内存。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值