# 07.App启动速度优化

### 一：启动时间

> 启动时间 = main()之前的时间 + main()之后的时间

#### 1.1 如何衡量时间

* 通过添加环境变量可以打印出APP的启动时间分析
  * `Edit scheme` -> `Run` -> `Arguments`
  * `DYLD_PRINT_STATISTICS` 设置为 `1`
  * 如果需要更详细的信息，那就将 `DYLD_PRINT_STATISTICS_DETAILS` 设置为 `1`

#### 1.2 作为开发者我们可以介入的地方有哪些？

![Image](/files/-MVqY0N6bXxyTQFNaicv)

### 二: main()之前

#### 2.1 dyld

`iOS`的动态链接器，可以用来装载`Mach-O`文件（可执行文件、动态库等）

* 启动APP时，`dyld`所做的事情有
  * 装载APP的可执行文件，同时会递归加载所有依赖的动态库
  * 当`dyld`把可执行文件、动态库都装载完毕后，会通知`Runtime`进行下一步的处理

#### 2.2 runtime

* 启动APP时，`runtime`所做的事情有
  * 调用`map_images`进行可执行文件(`.o`)内容的解析和处理
  * 在`load_images`中调用`call_load_methods`，调用所有`Class`和`Category`的`+load`方法
  * 进行各种`objc`结构的初始化（注册`Objc类` 、`初始化类对象`等等）
  * 调用`C++静态初始化器`和`__attribute__((constructor))`修饰的函数

到此为止，可执行文件和动态库中所有的符号(`Class`，`Protocol`，`Selector`，`IMP`，…)都已经按格式成功加载到内存中，被`runtime`所管理

#### 2.3 可优化点

* 减少不必要的`framework`
* `framework`应当设为`optional`和`required`，如果该`framework`在当前App支持的所有iOS系统版本都存在，那么就设为`required`，否则就设为`optional`，因为`optional`会有些额外的检查
* 合并或者删减一些OC类，关于清理项目中没用到的类，使用工具AppCode代码检查功能，查到当前项目中没有用到的类如
* 删除废弃方法
* `+load`里少做事情，用`+initialize`方法和`dispatch_once`取代所有的`__attribute__((constructor))`、`C++静态构造器`、`ObjC`的`+load`
* 尽量不用C++虚函数(创建虚函数有开销)
* `Swift`尽量使用`Struct`

### 三: main()之后

> 主要是App本身相关的一些初始化服务

* 不适用xib/sb,使用代码加载首页视图
* NSUserDefaults实际上是在Library文件夹下会生产一个plist文件，如果文件太大的话一次能读取到内存中可能很耗时，这个影响需要评估，如果耗时很大的话需要拆分(需考虑老版本覆盖安装兼容问题)
* 每次用NSLog方式打印会隐式的创建一个Calendar，因此需要删减启动时各业务方打的log，或者仅仅针对内测版输出log
* 梳理应用启动时发送的所有网络请求，是否可以统一在异步线程请求
* 首页相关控制器的`viewDidLoad`/`viewWillAppear`里少做操作或者延迟做
* 少做/不做 I/O 操作,或者异步做

### 参考

> <https://techblog.toutiao.com/2017/01/17/iosspeed/>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ryukiedev.gitbook.io/wiki/ios/you-hua/07.app-qi-dong-su-du-you-hua.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
