​ 你是否想过在按下app icon图标时到application::didFinishLaunchingWithOptions:?之间发生了什么

​ iPhone app技术上讲可以概括的描述为一个函数UIApplicationMain(::::)

​ 下面一起探究以下其中原理

UIApplication

​ 如果你研究UIApplicationMain(::::)这个方法,你会发现他的返回值是Int32类型.其实,这个方法从来不会真的退出,直到app退出,和你的app生命周期一致

​ 第一件事,app调用一个类UIApplication这个类非常重要,是控制,协同app运行的关键

​ 每个app只有一个该对象实例,是单例模式,UIApplication.shared就是这个单例对象

UIApplicationDelegate

​ 另一件事,创建AppDelegate,是一个遵守UIApplicationDelegate协议的对象,你可能对它已经很熟悉了,处理app交互的根对象

​ UIApplicationDelegate有一堆方法,用来管理你的app

​ 你是否注意到@UIApplicationMain标记在类声明之前?UIApplicationMain(::::)根据这个标记知道哪个类是Appdelegate.这个类也是和app的生命周期同步.也被指向为UIApplication的代理对象

​ 应用对象遇到重要的runtime事件时,会通知AppDelegate,例如app运行,内存警告,app终止,给予响应的机会

​ 在iOS13,上述的一些响应职责被SceneDelegate接手处理了.负责app生命周期的响应职责由appDelegate处理,一些和app显示,窗口交互的响应职责由sceneDelegate处理

Storyboard?

​ 此时,app的基础功能已经就绪了,UIApplicationMain(::::)开始准备处理交互了

​ 首先,需要找到main storyboard,这个行为是和Info.plist的key叫做”Main storyboard file base name”有关

​ 如果使用storyboard绘制界面,app会实例化UIWindow,UIVindow是UIView的子类.这个实例化的window是你用户界面的基础

​ 一旦实例化完成,window被赋值SceneDelegate的属性(在iOS13之前是AppDelegate的属性)

​ 如果你观察SceneDelegate里的scene(_:willConnectTo:options:)方法,你能注意到瞎买你的注释:

If using a storyboard, the window property will automatically be initialized and attached to the scene.

​ 现在开始window属性和app生命周期保持一致了

ViewController的初始化

​ 用户虽然创建了UIWindow的实例,但是现在却看不到任何东西的,用户并不会直接和window交互,能看到的是window里的rootViewController属性

​ rootViewController包含着你的initial view controller,你可以通过storyboard指定initial view controller,在”Attributes inspector”,选中”Is initial view controller”

​ 选中之后就被赋值给rootViewController属性,它是window现在唯一的直接的subview.其他的view都是rootview的subview

​ 现在是时候调用application:didFinishLaunchingWithOptions:方法了

​ 但window还是不可见,最一步需要调用makeKeyAndVisible()实例方法

​ 此时app已经就绪,功能开始执行了

无No Storyboard

​ 有些项目不使用storyboard,靠纯代码绘制界面,这种情况下,你必须要在UIApplicationMain里自己写相关代码

​ 在iOS13之前,写上述代码的位置在didFinishLaunchingWithOptions,现在要写在SceneDelegate里的 (_willConnectTo:options:)方法里

​ 你要写的代码内容:

  • 实例化UIWindow,赋值给SceneDelegate’s window属性
  • 实例化你的initial view controller并且赋值给windowrootViewController属性
  • 调用makeKeyAndVisible()展示界面

代码:

1
2
3
4
5
6
7
8
9
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

window = self.window ?? UIWindow()
window?.backgroundColor = .white
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()

guard let _ = (scene as? UIWindowScene) else { return }
}

总结

​ 上述的过程都是不可见的,在app内部处理,很多人没有思考过其中的细节.是app生命周期重要的部分