iOS面试题锦集

news/2024/7/20 22:49:15 标签: ios, cocoa, macos

1. 问:一张图片所占内存大小跟什么有关?

图片所占内存大小,与图片的宽高有关

我们平时看到的png、jpg、webp这些图片格式,其实都是图片压缩格式。通过对应的算法来优化了大小以节省网络传输与本地保存所需的资源。
但是当我们加载图片到内存中将要显示出来的时候是不能使用压缩格式,这样就不能显示图片了。

计算机依赖每一个像素点中的数据来显示图片。
例如iOS中的UIImange的每个像素点是由red+green+blue 三原色在加上alpha透明度组成的。
三原色每一个的范围在0 ~ 255所以需要1个字节来存储一个值的大小。
那么一个像素点的颜色就需要3个字节
再加上需要alpha的大小,alpha的范围是0~100 也是以1个字节来存储的。
所以一个像素点就需要4个字节来存储

疑问:
像素一定是RGB表示?必须是占4个字节?
像素会不会其他格式表示,从而造成所占字节数不同?

在这里插入图片描述

这样算来,一个image的size为100100,每个像素点占4个字节,那么
该图片的内存占用为:100
1004byte = 40000btye = 40001024KB

测试:

取一个图片,其大小是750x844
在这里插入图片描述

在这里插入图片描述

- (void)testImageSize
{
    UIImageView *imageView = [[UIImageView alloc] init];
    imageView.frame = CGRectMake(100, 100, 100, 100);
    imageView.image = [UIImage imageNamed:@"yz_life_share_gift_top_bg_image_2"];
    [self.view addSubview:imageView];
    
    //获取
    //The width, in pixels, of the specified bitmap image (or image mask).
    //指定位图图像(或图像掩码)的宽度(以像素为单位)。
    CGFloat imageWidth = CGImageGetWidth(imageView.image.CGImage);
    CGFloat imageHeight = CGImageGetHeight(imageView.image.CGImage);
    
    CGFloat imageMemorySize = imageHeight * imageWidth * 4 /1024/1024;
    NSLog(@"%f, %f, %f", imageWidth, imageHeight, imageMemorySize);
    //750.000000, 844.000000, 2.414703
    
    //或者
    //The number of bytes used in memory for each row of the specified bitmap image (or image mask).
    //指定位图图像(或图像掩码)的每一行在内存中使用的字节数。
    CGFloat bytesPerRow = CGImageGetBytesPerRow(imageView.image.CGImage);
    CGFloat imageMemorySize2 = imageHeight * bytesPerRow/1024/1024;
    NSLog(@"%f, %f, %f", bytesPerRow, imageHeight, imageMemorySize2);
    //3000.000000, 844.000000, 2.414703
}

也就是,一张11KB大小的图片,在内存中占用的内存大小是2.414703M

还是蛮大的

图片的大小?

首先,宽高,是指的图片本身的宽高,而不是mageView被设置的size

而图片的大小,可以用 单位为厘米 去测量,也可以用 单位为像素 去测量
比如100cm * 100cm大小的图片,其换算成像素为单位,并不是100px * 100px

本文章里,所讲的图片的大小,其实是以像素为单位的图片的大小

iOS uiimage内存占用大小计算

2. 问:为什么图片占用这么大的内存,而不是图片的原始大小?

这就要从图片格式来说,我们通常用的图片格式如:png和jpeg等,这些格式的图片都是压缩的位图格式,不能直接渲染展示在屏幕上,所以就需要在渲染到屏幕之前,需要将图片解压缩,得到图片的原始像素数据,过程如下:
在这里插入图片描述
即:Data Buffer、Image Buffer、Frame Buffer
Data Buffer 是存储在内存中的原始数据,图像可以使用不同的格式保存,如 jpg、png。是Image 的文件内容。
Image Buffer 是图像在内存中的存在方式,用于存放图像具体素点信息。Image Buffer 的大小和图像的大小成正比。
Frame Buffer 和 Image Buffer 内容相同,不过其存储在 vRAM(video RAM)中,而 Image Buffer 存储在 RAM 中。
解码就是从 Data Buffer 生成 Image Buffer 的过程。Image Buffer 会占用带宽上传到 GPU 成为 Frame Buffer,最后GPU负责使用 Frame Buffer用于更新显示区域。

3. 问:如何避免图片占用内存过大的问题呢?

方法一:

使用[UIImage imageNamed:@""];这种方式加载图片的话,图片会缓存在内存里面,不被释放
如果遇到频率使用低的图片、图片大的图片,建议使用[UIImage imageWithContentsOfFile:nil];这种方式加载图片

使用imageName:加载图片

  • 加载到内存当中会一直存在内存当中,(图片)不会随着对象的销毁而销毁。
  • 加载进去图片后,占用的内存归系统管理,我们是无法管理的。
  • 相同的图片是不会重复加载的
  • 加载到内存中占据的内存较大

使用imageWithContentOfFile:加载图片

  • 加载到内存中占据的内存较小
  • 相同的图片会被重复加载到内存当中
  • 加载的图片会随着对象的销毁而销毁

[UIImage imageNamed:]加载图片,与imageWithContentOfFile:加载图片有什么区别?

方法二:

使用UIGraphicsImageRenderer的API

如果ImageView的本身就是固定的200x200,加载800x800的图片会有什么问题?
答案:载入800x800的图片用到200x200的控件上是很浪费内存。需要消耗的内存大小800x800x4bit。

解决方案:在使用前把图片调整到需要的大小

因此,我们使用UIGraphicsImageRenderer,将图片大小调整为用户自己所需要的大小,以减少内存的使用

UIImage *image = [UIImage imageNamed:@"yz_life_share_gift_top_bg_image_2"];
//调用,或者直接传image.size.width
image = [self resiImage:image size:CGSizeMake(100, 100)];
imageView.image = image;

//方法
- (UIImage*)resiImage:(UIImage *)image size:(CGSize)size{
    UIGraphicsImageRenderer *re = [[UIGraphicsImageRenderer alloc]initWithSize:size];
    return [re imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {
        [image drawInRect:CGRectMake(0, 0, size.width, size.height)];
    }];
}

iOS Image 内存优化
UIGraphicsImageRenderer图片渲染优化



http://www.niftyadmin.cn/n/5431417.html

相关文章

记录一次难搞的编译错误-- qml-rust 项目编译无法找到QtCore库的问题

记录一次难搞的编译错误-- qml-rust 项目编译时无法找到QtCore库的问题 背景开始处理问题1 看日志找关键点2 写最简单测试用例3 写最简单CMake编译的Qt4 发现问题5 开始处理错误过程 1过程2过程3 反思开始找资料,解决自己的困惑。第二次开始解决问题第三次解决问题总…

软件杯 深度学习 opencv python 实现中国交通标志识别_1

文章目录 0 前言1 yolov5实现中国交通标志检测2.算法原理2.1 算法简介2.2网络架构2.3 关键代码 3 数据集处理3.1 VOC格式介绍3.2 将中国交通标志检测数据集CCTSDB数据转换成VOC数据格式3.3 手动标注数据集 4 模型训练5 实现效果5.1 视频效果 6 最后 0 前言 🔥 优质…

Stable Diffusion 模型下载:Juggernaut(主宰、真实、幻想)

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八 下载地址 模型介绍 该模型是一个真实模型,并且具有幻想和创意色彩。 作者述:我选取了…

【数学】【数论】【最大公约数】1819. 序列中不同最大公约数的数目

作者推荐 视频算法专题 本博文涉及知识点 数学 数论 LeetCode1819. 序列中不同最大公约数的数目 给你一个由正整数组成的数组 nums 。 数字序列的 最大公约数 定义为序列中所有整数的共有约数中的最大整数。 例如,序列 [4,6,16] 的最大公约数是 2 。 数组的一个…

DM数据库(docker)

docker安装 安装必要的系统工具 yum install -y yum-utils device-mapper-persistent-data lvm2 配置阿里云Docker Yum源: yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 更新yum缓存 yum makecache fast 安装docker-CE: y…

【Matlab】欧拉公式、梯形公式和改进欧拉公式求解常微分方程

求解代码实现 分别用欧拉公式、梯形公式和改进欧拉公式求解,并与精确解 y ( x ) = 1 + 2 x y(x)=\sqrt{1+2x} y(x)

vscode创建文件夹跟在后面,怎么解决?

如果你遇到类似问题。 按照以下操作即可。

第二十三章 Web 网关的配置基础知识

文章目录 第二十三章 Web 网关的配置基础知识Web 网关配置和日志文件自动路由到IRIS 的文件类型从 IRIS 提供静态文件表示字符编码 启用服务文件选项配置 Web 服务器以允许 IRIS 提供静态文件从 Web 服务器提供静态文件在高可用性解决方案的硬件负载均衡器上启用粘性会话启用脚…