App启动时间,直接影响用户对app的第一体验和判断.如果启动时间过长,不单用户体验会下降, 还有可能会触发苹果的watch dog机制而kill掉App, 所以App启动时间优化也十分重要
App启动流程
1 |
|
那么App的启动时间大致可分为两部分, 第一部分为main函数执行之前
的加载时间主要是系统的动态链接库和可执行文件的加载时间;第二部分是main函数开始到 application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
执行结束前的时间
main函数以前消耗的时间(pre-main)
首先需要在scheme中添加配置, 如下图
然后启动App就能在控制台看到如下信息, 时间消耗的项目十分明显, 如下所示:
1 |
|
main函数有花费的时间
面函数以后花费的时间主要是从main函数开始到 application:didFinishLaunchingWithOptions:
之间的时间, 方法如下:
main函数中记录时间的起点
1 |
|
application: didFinishLaunchingWithOptions:
中记录时间的终点, 取两者之差即可
1 |
|
如何减少main()调用之前的耗
-
减少不必要的framework,特别是第三方的,因为动态链接比较耗时
-
check framework应设为optional和required,如果该framework在当前App支持的所有iOS系统版本都存在,那么就设为required,否则就设为optional,因为optional会有些额外的检查;
-
合并或者删减一些OC类
-
删减一些无用的静态变量
-
删减没有被调用到或者已经废弃的方法
-
将不必须在+load方法中做的事情延迟到+initialize中
Swift如何计算启动时间
Swift项目是没有main文件,官方给了如下解释:
@UIApplicationMain to a regular Swift file. This causes the compiler to synthesize a mainentry point for your iOS app, and eliminates the need for a “main.swift” file.
也就是说,通过添加@UIApplicationMain
标志的方式,帮我们添加了mian函数了。所以如果是我们需要在mian函数中做一些其它操作的话,需要我们自己来创建main.swift文件,这个也是苹果允许的。
-
注释掉AppDelegate类中的 @UIApplicationMain标志;
-
自行创建
main.swift
(注意:main一定要小写, 不能写成Main否则报错)文件,并添加程序入口, 代码如下:1
2
3
4
5import UIKit var appStartLaunchTime: CFAbsoluteTime = CFAbsoluteTimeGetCurrent() UIApplicationMain(CommandLine.argc, UnsafeMutableRawPointer(CommandLine.unsafeArgv).bindMemory(to: UnsafeMutablePointer<Int8>.self,capacity: Int(CommandLine.argc)), nil, NSStringFromClass(AppDelegate.self))
-
然后在AppDelegate中编写如下代码:
1
2
3
4
5
6
7
8func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. // APP启动时间耗时,从mian函数开始到didFinishLaunchingWithOptions方法结束 DispatchQueue.main.async { print("APP启动时间耗时,从mian函数开始到didFinishLaunchingWithOptions方法:\(CFAbsoluteTimeGetCurrent() - appStartLaunchTime)。") } return true }