iOS 【程序启动原理/手动创建UIWindow/UIApplicationMain做了些什么/makeKeyAndVisible底层实现】

一、什么是UIWindow(★★★ )
UIWindow是一种特殊的UIView,通常在一个app中 至少有一个UIWindow
iOS程序 启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的view,
最后将控制器的view添加到UIWindow上,于是控制器的view就显示在屏幕上了
一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWindow

二、程序启动阶段 UIWindow 的加载过程(★★★★★)
1、执行main(main.m文件)
int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}
代码解释:
int main(int argc, char * argv[]) {
     @autoreleasepool {
          第三个参数:UIApplication类名或者子类的名称 nil == @"UIApplication"
          第四个参数:UIApplication的代理的代理名称
          NSStringFromClass:把类名转化字符串
          NSStringFromClass好处:1.有提示功能 2.避免输入错误
          return UIApplicationMain(argc, argv, nil,NSStringFromClass([AppDelegate class]));
     }
}

    
2、执行UIApplicationMain。(应用程序启动原理)
UIApplicationMain{ // UIApplicationMain 做了些什么
2.1. 会创建UIApplication对象,并设置指定的代理。
2.2. 开启一个主运行循环又称事件循环(死循环,保证应用程序不退出);
2.3. 加载工程的配置文件(info.plist)在加载info.plist时会判断info.plist的 Main storyboard file base name 项,看该项有没有指定Main.storyboard(选项中是填的 Main)。
 
  如果指定Main,就会加载 Main.storyBoard文件。加载时会做以下几件事
 ① 首先先去帮你创建一个UIWidow;
 ② 把Main.storyBoard当中箭头指向的控制器,设置为窗口的rootViewController。(每一个window必须得有rootViewController)
 ③ 在窗口显示时,把窗口的根控制器的view添加到窗口上。
 
 如果没有指定Main(并不会影响接下来的执行),继续执行下一步(如果手动创建,则显示手动创建的window视图。如果没有手动创建也没有加载到合适的sb,那么就GG,程序运行结果一片黑,但不会崩溃)。

2.4. 调用应用程序代理方法,告诉应用程序启动完毕。
当info.plist文件没有找到的时候,那么程序就加载完毕,那么在程序加载完毕时要自己手动去创建窗口。


手动创建窗口的步骤:
创建窗口,要有窗口显示,必须要有强引用。窗口也是控件,要想展示出来,必须得要有尺寸。
首先,创建项目的时候,在AppDelegate.h中已经自动创建好了一个强指针。

设置尺寸:self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];


创建控制器并设置为窗口的根控制器

注意:一开始想显示谁,就设置窗口的根控制器为谁。

UIViewController *vc = [[UIViewController alloc] init];
// vc.view.backgroundColor = [UIColor redColor];

self.window.rootViewController = vc;

显示窗口

[self.window makeKeyAndVisible];

三、几点补充
1、AppDelegate 的代理方法
// 当应用程序启动完成时自动调用
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSLog(@"%s",__func__);
    return YES;
}

// 当应用程序失去焦点时调用(失去焦点:不能与用户进行交互)
- (void)applicationWillResignActive:(UIApplication *)application {
     NSLog(@"%s",__func__);
}

// 当应用程序进入后台时调用
- (void)applicationDidEnterBackground:(UIApplication *)application {
    NSLog(@"%s",__func__);
}
// 当应用程序即将进入前台时调用
- (void)applicationWillEnterForeground:(UIApplication *)application {
  NSLog(@"%s",__func__);
}

// 当应用程序获取焦点时调用(能够与用户进行交互)
- (void)applicationDidBecomeActive:(UIApplication *)application {
    NSLog(@"%s",__func__);
}

// 当应用程序挂掉时调用
- (void)applicationWillTerminate:(UIApplication *)application {
     NSLog(@"%s",__func__);
}

// 当应用程序收到内存警告时调用
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
     NSLog(@"%s",__func__);
    // 清理缓存
}

2、 [self.window makeKeyAndVisible] 显示窗口 语句的底层实现
① 让窗口成为显示状态
窗口默认是隐藏的.hidden = yes
底层做的事件就是:
self.window.hidden = NO;
② 把根控制器的View添加到窗口上面(我们是在控制器内添加控件view,而控制器会把view添加到window上面显示)
[self.window addSubView:rootVC.view];
③ 把当前窗口设置成应用程序的主窗口
[UIApplication sharedApplication].keyWindow = self.window; // 注意获得应用程序主窗口的方式

你可能感兴趣的:(iOS)