ios进阶-包大小:如何从资源和代码层面实现全方位瘦身(代码片段)

极客学伟 极客学伟     2022-11-30     575

关键词:

iOS进阶 - 包大小:如何从资源和代码层面实现全方位瘦身

官方 App Thinning

App Thinning 是由苹果公司推出的一项可以改善 App 下载进程的新技术,主要为了解决用户下载 App 耗费过高流量的问题,同时还可以节省用户 iOS 设备的存储空间。

App Thinning 会专门针对不同的设备来选择只适用于当前设备的内容以供下载。比如,iPhone 6 只会下载 @2x 分辨率的图片资源,iPhone 6Plus 则只会下载 @3x 分辨率的图片资源。

在苹果公司使用 App Thinning 之前,每个App都包含多个芯片的指令集架构文件。使用 App Thinning 之后,用户下载时就只会下载一个适合自己设备的芯片指令集架构文件。

App Thinning 包含三种方式,包括:App Slicing、Bitcode、On-Demand Resources。

  • App Slicing 会在你想 iTunes Connect 上传 App 后,对 App 做切割,创建不同的变体,这样就可以适用到不同的设备
  • On-Demand Resources 主要视为游戏多关卡场景服务的,它会根据用户的关卡金服下载随后几个关卡的资源,并且已经过关的资源也会被删掉,这样就可以减少初装 App 的包的大小。
  • Bitcode 是针对特定设备进行包大小优化,优化不明显

其实,这里的大部分工作都是由 Xcode 和 App Store 来帮你完成的,你只需要通过 Xcode 添加 scassets 目录,然后将图片添加进来即可。所添加的 @2x 分辨率的图片和 @3x 分辨率的图片会在上传到 App Store 后被创建成不同的变体以减小 App 安装包的大小。而芯片指令集架构文件只需要按照默认的设置,App Store 就会根据设备创建不同的变体,每个变体里只有当前设备需要的那个芯片指令集架构文件。

其他无用图片资源

图片资源的优化空间主要体现在删除无用图片和图片资源压缩两个方面。而删除无用图片,又是其中最容易的、最应该先做的。

删除无用图片

三方库 LSUnusedResources 可以帮助我们定位到项目中无用的图片

图片资源压缩

目前比较好的压缩方案是将图片转成 WebP, WebP 压缩率高,而且肉眼看不出差异,同时支持有损和无损压缩模式,比如将 Gif 图片转成 Animated WebP, 有损压缩模式可减少 64% 大小,无损压缩模式可减少 19% 大小。
WebP 支持 Alpha 透明和 24-bit 颜色数,不会像 PNG8 那样因为色彩不够而出现毛边。
谷歌提供了一个图片压缩工具 cwebp 来将其他图片转成 WebP. cwebp 使用起来也很简单,只要根据图片情况设置好参数就行。

cwebp 语法:

cwebp [options] input_file -o output_file.webp

比如将 original.png 进行无损压缩,可以使用如下命令:

cwebp -lossless original.png -o new.webp

其中 -lossless 表示的是,要对输入的 png 图像进行无损编码,转成 WebP 图片,不使用 -lossless 则表示有损压缩。

在 cwebp 语法中,还有一个比较关键的参数 -q float

图片色值在不同情况下,可以选择用 -q 参数来进行设置,在不损失图片质量情况下进行最大化压缩。

  • 小于 256 色适合无损压缩,压缩率高,参数使用 -lossless -q 100;
  • 大于 256 色使用 75% 有损压缩,参数使用 -q 75;
  • 远大于 256 色使用 75% 以下压缩率,参数 -q 50 -m 6。

除 cwebp 以外,也可以使用 iSparta 实现 PNG 格式转 WebP ,如果是其他格式图片则可先将其转成 PNG 再转成 WebP 。

压缩完图片我们还需要使用 libwebp 进行解析。这里有一个iOS工程使用 libwebp 的范例 WebP-iOS-example

不过,WebP 在 CPU 消耗和解码时间上会比 PNG 高两倍。所以,我们有时候还需要在性能和体积上做取舍

代码瘦身

App 安装包主要有资源文件和可执行文件组成,所以我们在掌握了对图片资源的处理方法后,还需要对可执行性文件进行瘦身。

可执行文件就是 Mach-O 文件,其大小是由代码量决定的,通常情况下,对可执行文件进行瘦身,就是 找到并删除无用代码的过程 。查找无用代码思路同查找无用图片

  • 找出方法和类的全集
  • 找到使用过的方法和类
  • 取二者的差集得到无用代码
  • 最后人工确定无用代码可删除后,进行删除即可。
使用machoview

可以使用 machoview 这个软件查看 Mach-O 文件里的信息,如何使用:

  • 首先,我们需要编译一个 App。在这里,我 clone 了一个 GitHub 上的示例 GCDFetchFeed 下来编译。
  • 然后,将生成的 GCDFetchFeed.app 包解开,取出 GCDFetchFeed。
  • 最后,我们就可以使用 MachOView 来查看 Mach-O 里的信息了。

我们可以看到 __objc_selrefs (一定是被调用了的)__objc_classrefs (被调用过的类) 和、__objc_superrefs (调用过 super 的类) 这三个 section。

但是这种查看方法并不完美,原因在于 Objective-C 是一门动态语言,方法钓鱼可以写成在运行时动态调用,这样就无法收集全所有调用的方法和类。所以,通过此种方法找到的无用的方法和类还需要进行手动二次确认。

通过 AppCode 查找无用代码

AppCode 里选择 Code->Inspect Code 就可以进 行静态分析。静态分析完以后,我们可以在 Unused code 里看到所有的无用代码,

AppCode 静态检查的问题:

  • JSONModel 里定义了未使用的协议会被判定为无用协议;
  • 如果子类使用了父类的方法,父类的这个方法不会被认为使用了;
  • 通过点的方式使用属性,该属性会被认为没有使用;
  • 使用 performSelector 方式调用的方法也检查不出来,比如 self performSelector:@selector(arrivalRefreshTime);
  • 运行时声明类的情况检查不出来。比如通过 NSClassFromString 方式调用的类会被查出为没 有使用的类,比如 layerClass = NSClassFromString(@“SMFloatLayer”)。还有以 [[self class] accessToken] 这样不指定类名的方式使用的类,会被认为该类没有被使用。像 UITableView 的自定义的 Cell 使用 registerClass,这样的情况也会认为这个 Cell 没有被使用。

基于以上种种原因,使用 AppCode 检查出来的无用代码,还需要人工二次确认才能够安全删除掉。

浅析如何减小ios版微信安装包的大小

引用资源“减肥”资源瘦身主要是去掉无用资源和压缩资源,资源包括图片、音视频文件、配置文件以及多语言wording。无用资源是指资源在工程文件里,但没有被代码引用。检查方法是,用资源关键字(通常是文... 查看详情

unity之addressable可寻址系统--资源热更新--进阶(代码片段)

可寻址系统远程加载--资源热更新--进阶(四)一,本地实现资源热更1.1资源热更概念1.2具体实现步骤1.3本地资源热更二,AA+CCD实现资源热更2.1工程设置2.2实现热更概述:Unity可寻址系统的资源热更是我遇到... 查看详情

从网站加载 iOS 应用程序资源

...:由于视频和声音文件的大量使用,我目前正在开发一个大小已超过100mb的通用iOS应用程序。我已经实现了在运行时(从网站)加载这些资产的解决方案,但我想知道Apple是否批准此类操作。它现在的工作方式是这样的:为每个iO... 查看详情

从汇编层面看函数调用的实现原理(代码片段)

...执行和调用过程。本节我们需要重点关注的问题有:CPU是如何从调用者跳转到被调用函数执行的?参数是如何从调用者传递给被调用函数的?函数局部变量所占内存是怎么在栈上分配的?返回值是如何从被调 查看详情

如何学习一门语言

...建过程git:  源代码控制IDEjenkins:自动化集成底层和进阶底层——内存相关:内存堆(heap)和线程栈JMMGC(garbagecollection):GClog分析和GC调优底层——JVM和Java相关规范JVM+JAVA字节码Class文件格式ClassLoader进阶多线程... 查看详情

kettle资源和学习资料精选,kettle从入门到迅速进阶,看这篇就够了!

...后回复“Kettle”获取,资料目录如下所示: Kettle进阶文章精选1、Kettle的下载和简介;2、Kettle常用的两种数据库连接方式;3、Kettle使用概述:围绕ETL主要过程,提供一份完整的数仓开发路线图;4、Kett... 查看详情

面向对象进阶2(代码片段)

目录类的封装封装是什么封装的两个层面第一个层面第二个层面私有模块类的property特性什么是property特性property属性的两种方式装饰器类与对象的绑定方法和非绑定方法绑定方法对象的绑定方法类的绑定方法非绑定方法类的封装... 查看详情

android包体积优化(常规进阶极致)(代码片段)

前言包大小的重要性已经不需要多说,包大小直接影响用户的下载,留存,甚至部分厂商预装强制要求必须小于一定的值。但是随着业务的迭代开发,应用会越来越大,安装包会不停的膨胀,因此包大小缩... 查看详情

koa2从入门到进阶之路(代码片段)

之前的文章我们介绍了一下koapost提交数据及koa-bodyparser中间件,本篇文章我们来看一下 koa-static静态资源中间件。 我们在之前的目录想引入外部的js,css,img等静态资源该如何获取呢?我们首先先按照之前的思维按照相对... 查看详情

前端性能优化成神之路-总结(代码片段)

...面,浏览器渲染层面,服务端层面 具体的优化点有:资源合并与压缩,图片编码原理和类型的选择,浏览器的渲染机制,懒加载与预加载,浏览器存储,缓存机制,PWA,Vue-SSR等等  首先来了解一下web前端的本质web前... 查看详情

go使用go语言打造定时提醒小工具,从基础到优化全方位探索(代码片段)

一、引言1.目的和背景本文和大家分享编程语言对于时间和日期的处理方式,以及代码的优化思路。2.选择GO语言的原因简单易学:GO语言的语法简单易学,这使得初学者能够快速上手,减少学习成本。高效性能:GO语言的编译器... 查看详情

nsoperation的进阶使用和简单探讨(代码片段)

本文将会从这多个方面探讨NSOperation类和NSOperationQueue类的相关内容一、简介NSOperation的是iOS2.0推出的,通过NSThread实现的,但是效率的确一般。从OSX10.6和iOS4推出GCD时,又重写了NSOperation和NSOperationQueue,NSOperation和NSOperationQueue分别... 查看详情

如何从xml中的另一个包加载资源?

】如何从xml中的另一个包加载资源?【英文标题】:Howtoloadresourcefromanotherpackageinxml?【发布时间】:2013-03-2915:07:45【问题描述】:我知道存在这样的代码从另一个包安装资源xml文件的能力:StringresourceName=getResources().getResourceEntryNa... 查看详情

企业数字化转型的重要性

...的数字、从物理形态的数字转变成虚拟形态的数字,打通全方位、全过程、全领域的数据实时流动与共享,实现信息技术与业务管理的真正融合,发挥数据的价值;3.在企业“重构”层面,适应互联网时代和智能时代的需要,基于... 查看详情

iOS:从起点给定距离和方位的目标点

】iOS:从起点给定距离和方位的目标点【英文标题】:iOS:Destinationpointgivendistanceandbearingfromstartpoint【发布时间】:2011-04-1215:52:28【问题描述】:给定起点、初始方位和距离,这将计算沿(最短距离)大圆弧行进的目的地点和最终... 查看详情

入门」全方位盘点和总结调优技术专题指南(代码片段)

专题⽬标本系列专题的目标是希望可以帮助读者们系统和全访问掌握应⽤系统调优的思路与方案以及相关的调优工具的使用,虽然未必会覆盖目前的所有的问题场景,但是还是提供了较为丰富的案例和调优理论,会帮... 查看详情

unity如何打包apk能压缩资源

如何在unity中打包apk能有效的压缩资源,比如图片的大小,我发现直接修改图片的大小之后打包好像不能压缩资源,打出来的包都是原来的大小。谁能告诉下如何能压缩资源unity3d开发3d游戏,不可避免的要用到大量的模型、图片... 查看详情

unity性能优化专题—腾讯牛人分享经验(难度1推荐3)

...前因为老大要求,要把unity最终发布的包压缩到至少之前大小的一半,这可难倒我了,不过最终还是在问了很多大神后解决了,主要是在本文章中讲的“二”。 tag: unity素材压缩、unity资源压缩、unity压缩包大小、unity怎么... 查看详情