iOS 应用启动优化简述

iOS 应用启动优化简述

简单来说,一个应用的启动过程是指,用户点击应用图标开始,到用户看到该应用的第一个界面为止。具体可以分为下面几个时间段:

  1. 用户点击应用图标~main函数执行前

    在该阶段,系统会加载可执行文件(应用的 .o 文件集合),加载动态链接库,调整 rebase 指针并进行符合绑定。Objc 会初始化,包括 Objc 相关类的注册,分类(category)的注册以及选择器(selector)的唯一性检查等。并且,初始化时,各个类的 +load() 方法会被执行,且 C++ 静态全局变量会被声明等。

    为减少应用启动时间,相应的可以减少动态库的加载,减少 C++ 全局变量的声明,移除无用的类或方法,+load() 中的操作可以延后的延后,或者放在 +initialize() 方法中执行。

  2. main函数开始执行~首屏渲染之前

    int main(int argc, char * argv[])
    {
        @autoreleasepool {
            return UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate class]));
        }
    }
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        // Override point for customization after application launch.
        return YES;
    }
    

    这个阶段实际是指从代理类的 application: didFinishLaunchingWithOptions 方法开始到所有与首屏渲染相关的代码执行完毕为止。这些代码执行的目的,可能会是去读取本地配置、请求服务器上的数据或者进行一些必要的计算等。

    所以为了节省时间,应当将与首屏渲染无关的操作放在首屏渲染完成后。

  3. 首屏渲染完成后

    这个阶段实际是指首屏渲染代码完成后到 application: didFinishLaunchingWithOptions 方法结束之前的所有操作,虽然这部分的操作并不会妨碍用户看到首屏,但是如果耗时太长,会使得主线程无法响应用户手势,造成界面卡顿。

    所以这个阶段不宜存在大量计算或读写文件等耗时操作,可以单开一个线程执行相关操作。


类方法 +initialize() 与 +load()

+ (void)initialize;

当运行时第一次向一个类发送消息时,该方法便会被执行,并且该方法只自动执行一次且是线程安全的,其他线程向该类发送的消息都会被阻塞,直到初始化方法结束。

通常情况,不应该主动去调用该方法,但是也存在子类主动调用父类的初始化方法,所以可以使用下面的写法,来避免自己定义的初始化任务被重复执行。

+ (void)initialize {
  if (self == [ClassName self]) {
    // ... do the initialization ...
  }
}

这里的 self 很特殊,虽然 - (instancetype)self; 声明为一个实例方法,但是可以作为类方法使用。

当类或者分类被加入到 Objective-C 运行时中时,可以实现下面的方法,对该类进行一些特殊处理,如 hook 处理。

+ (void)load;

初始化方法的执行的顺序为:

  • 其所链接的库
  • 其本身二进制文件中的 +load 方法
  • C++ 静态变量初始化以及被 __attribute__(constructor) 修饰的函数
  • 其他链接到该库的库

参考

iOS开发-APP启动main()调用之前的加载过程

iOS APP 启动性能优化

iOS 启动时间优化

发布了129 篇原创文章 · 获赞 23 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/u011374318/article/details/103997660