app启动过程分析

前言

文章中的观点主要通过阅读苹果官方文档和代码调试结果得出,如有偏差或者遗漏的地方,欢迎留言指出。

app启动过程分析_第1张图片
image

这张图来自于苹果的官方文档,大致描述了app的启动流程,可以先跳过不看。

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

在Xcode中打开main.m文件,可以看到在main方法中调用了UIApplicationMain方法,这个方法承载了app启动过程中的三个主要工作:

  1. 根据方法的第三个参数,创建UIApplication对象。如果参数为nil, 则使用UIApplication类。这个UIApplication对象会以单例的方式存在于app的整个生命周期,直到app退出;

  2. 根据第四个参数,创建UIApplication Delegate对象;

  3. 创建主事件循环(RunLoop)并启动

  4. 加载info.plist, 如plist文件中配置了StoryBoard, 则加载Storyboard中的view.

虽然UIApplicationMain有返回值,但是在整个程序运行期间不会返回,只有在app退出时才会返回。

实践才是检验真理的唯一标准!

验证一: UIApplication对象和RunLoop对象的创建

创建一个新的工程,并打开main.m 文件,在main方法体内打上断点
,同时在AppDelegate.m的- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法体内也打上断点,重新运行一下项目。

项目会停留在main方法中,在debug窗口中打印UIApllication对象和RunLoop对象

po [UIApplication sharedApplication] //返回nil
po [NSRunLoop currentRunLoop].currentMode //返回nil

继续执行程序,程序会停留在didFinishLaunchingWithOptions方法体内,在debug窗口中再次打印UIApplication对象和RunLoop对象

po [UIApplication sharedApplication] //返回
po [NSRunLoop currentRunLoop].currentMode   //返回UIInitializationRunLoopMode

由此可得出,UIApplication对象和RunLoop事件循环在UIApplicationMain方法中被创建。

验证二:Storyboard的加载

Xcode会在新建的工程中自动创建一个Main.storyboard文件,并在info.plist配置好。保留验证一里设置的AppDelegate中设置的断点,重新运行程序,在断点出打印self.window.rootViewController属性

 po self.window.rootViewController //

由此可见,Main.storyboard在didFinishLaunchingWithOptions回调方法之前已经被自动加载并设置为window的根对象。

删除info.plist中的Main storyboard file base name这一项,重新运行项目,在didFinishLaunchingWithOptions方法中打印self.window

 po self.window // nil

验证三:无论是否有storyboard,didFinishLaunchingWithOptions中回调中都可以设置self.window的rootViewController

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    self.window = [[UIWindow alloc] init];
    self.window.rootViewController = [[ViewController alloc] init];
    [self.window makeKeyAndVisible];
    return YES;
}

分别尝试有storyboard的情况和无storyboard的情况,通过验证可以得出如果有storyboard, UIApplicationMain会先加载storyboard,如果没有,则需要使用代码在didFinishLaunchingWithOptions回调方法里创建self.window对象。

最后梳理一下app启动过程:

  1. 调用main()方法;

  2. 调用并进入UIApplicationMain()方法, 直到程序退出时方法才会退出。其内部的执行顺序为:

    a. 创建UIApplication对象;

    b. 创建UIApllication的delegate对象;

    c. 加载info.plist文件,如果配置有storyboard文件名,则加载 storyboard;

    d. 开启一个主线程的RunLoop,监听事件。

现在,可以回头看下苹果的流程图。

你可能感兴趣的:(app启动过程分析)