本篇文章讲解ios的应用程序的启动
首先,我们在手机上点击一个app图标
代码指令并不是从main函数开始执行的,在main函数之前还有一系类的关于代码的初始化操作,比如:
int main(int argc, char * argv[]) {
NSString * appDelegateClassName;
@autoreleasepool {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
上面代码是一个main函数的执行代码,一般我们不需要修改这个函数中的代码,main函数主要的操作就是执行函数UIApplicationMain,该函数的原型如下:
// argc、argv:直接传递给UIApplicationMain进行相关处理即可
// principalClassName:指定应用程序类名(app的象征)
// 该类必须是UIApplication(或子类)。
// 如果为nil,则用UIApplication类作为默认值
// delegateClassName:指定应用程序的代理类,该类必须遵守UIApplicationDelegate协议
int UIApplicationMain(int argc, char * _Nullable argv[_Nonnull], NSString * _Nullable principalClassName, NSString * _Nullable delegateClassName);
@interface AppDelegate : UIResponder
苹果公司在iOS 13的时候引入了多窗口的概念
。Launch screen interface file base name
,程序会先加载Launch screen界面,这是个启动界面Main storyboard file base name
,程序会加载Main storyboard界面,该文件中保存了我们app的Root View Controller,否则直接跳到下一步Main storyboard file base name
,然后又在该函数内创建了一个新界面,新界面会覆盖之前的界面。- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
在IOS 13之前,应用程序的状态监听都是通过UIApplicationDelegate协议实现的,下面列出常用的UIApplicationDelegate协议。
// 该方法是程序启动,但还没进入状态保存时执行。
// 该方法在启动界面之后执行
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions API_AVAILABLE(ios(6.0));
// 该方法是程序启动基本完成,准备开始运行时执行。
// 该方法在启动界面之后执行,一般需要在该方法内创建主界面
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions API_AVAILABLE(ios(3.0));
// 该方法是当程序将要进入非活动状态时执行,在此期间,应用程序不接收消息或事件,比如按下Home键或者来电话了。
- (void)applicationWillResignActive:(UIApplication *)application
// 该方法是当程序已经进入后台时执行
- (void)applicationDidEnterBackground:(UIApplication *)application
// 该方法是当程序将要进入前台时执行
- (void)applicationWillEnterForeground:(UIApplication *)application
// 该方法是当程序进入活动状态时执行
- (void)applicationDidBecomeActive:(UIApplication *)application
// 该方法是当程序程序将要退出时执行
- (void)applicationWillTerminate:(UIApplication *)application
如果我们设置ios程序的Mimimum Deployments的iOS版本小于13,程序依旧采用上述的UIApplicationDelegate协议,但是如果我们的iOS版本大于13,上述UIApplicationDelegate协议的
都不会执行,因为这几种状态被认为是scene的状态改变而不是应用程序的状态改变了。事实上,info.plist的加载都需要改变。
为了实现多窗口功能,苹果修改了使用多年的AppDelegate,把AppDelegate分为了两部分,AppDelegate和SceneDelegate,其中
// 新建场景时会调用,返回场景配置信息
// 我们一般在这个里面记载Scene Configuration
// 下面是一个例子:return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options
// 关闭场景时调用
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions
// 配置UIWindow“窗口”并将其附加到所提供的UIWindowScene“场景”
// 如果在配置文件中配置了storyboard。UIWindow“窗口”将自动初始化并附加到场景
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions
// 在系统释放场景时或者场景进入后台调用
- (void)sceneDidDisconnect:(UIScene *)scene
// 当场景从非活动状态移动到活动状态时调用。
// 使用此方法可以重新启动场景处于非活动状态时暂停(或尚未启动)的任何任务。
- (void)sceneDidBecomeActive:(UIScene *)scene
// 当场景将从活动状态移动到非活动状态时调用。
// 比如来电话或切入后台
- (void)sceneWillResignActive:(UIScene *)scene
// 在场景从背景过渡到前景时调用。
- (void)sceneWillEnterForeground:(UIScene *)scene
// 场景进入后台后调用
- (void)sceneDidEnterBackground:(UIScene *)scene
程序支持的场景需要在Info.plist中声明,由Info.plist->Application Scene Manifest->Scene Configuration->Application Session Role节点指定场景List,每一项包含以下节点:
使用Scene Delegate之后,UIApplicationDelegate将不再持有UIWindow,它将转移至UIWindowSceneDelegate代理中
最后我们从加载配置文件开始重新梳理一下对于大于IOS13的启动过程
configurationForConnectingSceneSession协议
,该协议会返回默认加载场景的UISceneConfiguration*Info.plist->Application Scene Manifest->Scene Configuration->Application Session Role
中寻找场景列表,如果有,根据上一步返回的值匹配应该加载哪个场景,如果上一步返回nil,匹配列表中的第一个。如果列表为空,不加载场景,这时候应该是黑屏