zoukankan      html  css  js  c++  java
  • iOS:App启动过程详解

    以上是Xcode4.2中不采用storyboard应用的默认启动流程图。对于采用了storyboard的应用,UIApplicationMain()

    将会额外加载应用的主要storyboard文件,从而创建窗口和初始视图。

    程序启动的完整过程

    1.main函数

    2.UIApplicationMain

    * 创建UIApplication对象

    * 创建UIApplication的delegate对象

    3.delegate对象开始处理(监听)系统事件(没有storyboard)

    * 程序启动完毕的时候, 就会调用代理的application:didFinishLaunchingWithOptions:方法

    * 在application:didFinishLaunchingWithOptions:中创建UIWindow

    * 创建和设置UIWindow的rootViewController

    * 显示窗口

    3.根据Info.plist获得最主要storyboard的文件名,加载最主要的storyboard(有storyboard)

    * 创建UIWindow

    * 创建和设置UIWindow的rootViewController

    * 显示窗口

    一、UIApplicationMain这个函数主要负责三件 事情: 

    1)从给定的类名初始化应用程序对象,也就是初始化UIApplication或者子类对象的一个实例,如果你在这里给定的是nil,那么 系统会默认UIApplication类,也就主要是这个类来控制以及协调应用程序的运行。在后续的工作中,你可以用静态方法sharedApplication 来获取应用程序的句柄。 
     

    2)从给定的应用程序委托类,初始化一个应用程序委托(UIApplicationDelegate)。并把该委托设置为应用程序的委托,这里就有如果传入参数为nil,会调用函数访问 Info.plist文件来寻找主nib文件,获取应用程序委托。 
     

    3)启动主事件循环,并开始接收事件。

    二、UIApplication(或 者子类)对象的职责,这个对象主要做下面几件事: 
     

    1)负责处理到来的用户事件并分发事件消息到应该处理该消息的目标对象(sender,  action)。 


     2)管理以及控制视图,包括呈现、控制行为、当前显示视图等。 


     3)该对象有一个应用程序委托对象,当一些生命周期内重要事件(可以包括系统事件或者生命周期控制事件)发生时,应用程序通知该对象。例如,应用程序启 动、内存不够了或者应用程序结束等,让这些事件发生时,应用程序委托去响应。 

    UIApplication有以下成员变量
        1、sharedApplication类方法获取当前程序的UIApplication实例
        2、delegate属性获取UIApplicationDelegate实现类的实例
        3、windows属性获取当前程序涉及到窗口类数组 
        4、keyWindow属性获取当前程序关键窗口

    所以当前的windows存放在UIApplication中。

    以上流程图是没有加载sb的,以下是加载sb的流程:

    -.先执行main函数,main内部会调用UIApplicationMain函数
    --.UIApplicationMain函数里面做了什么事情:
    1.调用UIApplicationMain()函数;
    2.创建UIApplication对象;
    3.创建UIApplication的delegate对象-----XXAppDelegate;
    4.加载Info.plist文件,读取最主要storyboard文件的名称;
    5.UIApplication开启一个消息循环
    * 每监听到对应的系统事件时,就会通知MJAppDelegate;
    6.UIApplication调用相关代理方法;
    ------------我是分割线------------
    7.为应用程序创建一个UIWindow对象(继承自UIView),设置为XXAppDelegate的window属性;
    8.加载最主要的storyboard文件,创建白色箭头所指的控制器对象;
    9.并且将8步奏里创建的控制器为UIWindow的rootViewController属性(根控制器);
    10.展示UIWindow,展示之前会将添加rootViewController的view到UIWindow上面(在这一步才会创建控制器的view)
        [window addSubview: window.rootViewControler.view];
    ------------end------------
     
      **用例1**:不使用storyboard,程序启动后进入application:didFinishLaunchingWithOptions方法,该方法内部什么都不实现
    1. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
    2.     // Override point for customization after application launch.    
    3.     return YES;  
    4. }  
          结果:程序启动,屏幕一片漆黑。
          用例1分析:程序启动,didFinishLaunchingWithOptions方法里没有加载任何视图(还有window原因,见下面用例)。
          **用例2**:不使用storyboard,程序启动后进入application:didFinishLaunchingWithOptions方法,该方法内部创建添加需要显示的内容。
    1. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
    2.     // Override point for customization after application launch.  
    3.      
    4.     TableViewController *tableViewController = [[TableViewController alloc]initWithStyle:UITableViewStylePlain];      
    5.     [self.window addSubview:tableViewController.view];      
    6.     [self.window makeKeyAndVisible];  
    7.     return YES;  
    8. }  
          结果:程序启动,屏幕一片漆黑
          **用例3**:不使用storyboard,程序启动后进入application:didFinishLaunchingWithOptions方法,该方法内部创建UIWindow,并创建添加需要显示的内容。
    1. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
    2.     // Override point for customization after application launch.  
    3.       
    4.     self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];  
    5.     TableViewController *tableViewController = [[TableViewController alloc]initWithStyle:UITableViewStylePlain];      
    6.     [self.window addSubview:tableViewController.view];      
    7.     [self.window makeKeyAndVisible];  
    8.     return YES;  
    9. }  
           结果:程序启动,显示tableviewController的视图,正常。
           用例2+用例3分析:当不用storyboard的时候,AppDelegate被创建完之后,它的window属性为空,需要手动创建之。然后再用它
          **用例4**:使用storyboard,程序启动后进入application:didFinishLaunchingWithOptions方法,该方法内部创建添加需要显示的内容
            (备注:storyboard里面初始化的控制器为ViewController,并且在相关方法输出了_cmd)
    1. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
    2.     // Override point for customization after application launch.  
    3.      
    4.     NSLog(@"here1");  
    5.     NSLog(@"%@",self.window);  
    6.     TableViewController *tableViewController = [[TableViewController alloc]initWithStyle:UITableViewStylePlain];    
    7.     NSLog(@"here2");    
    8.     [self.window addSubview:tableViewController.view];  
    9.     NSLog(@"here3");  
    10.     return YES;  
    11. }  
            结果:输出,界面显示ViewController的界面
    1. 2014-09-20 16:30:22.066 Refer[3253:60b] ViewController : initWithCoder:  
    2. 2014-09-20 16:30:22.074 Refer[3253:60b] here1  
    3. 2014-09-20 16:30:22.077 Refer[3253:60b] <UIWindow: 0x14db9020; frame = (0; 32480); hidden = YES; gestureRecognizers = <NSArray: 0x14db9cb0>; layer = <UIWindowLayer: 0x14dbb910>>  
    4. 2014-09-20 16:30:22.079 Refer[3253:60b] here2  
    5. 2014-09-20 16:30:22.091 Refer[3253:60b] TableViewController : viewDidLoad  
    6. 2014-09-20 16:30:22.095 Refer[3253:60b] here3  
    7. 2014-09-20 16:30:22.104 Refer[3253:60b] ViewController : viewDidLoad  
            分析用例4:tableviewController的界面不显示,可能是被viewController界面覆盖了,还是某种原因。
         **用例5**:使用storyboard,程序启动后进入application:didFinishLaunchingWithOptions方法,该方法内部创建添加需要显示的内容
    1. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
    2.     // Override point for customization after application launch.  
    3.      
    4.     NSLog(@"here1");  
    5.     NSLog(@"%@",self.window);  
    6.     NSLog(@"%@",self.window.rootViewController);  
    7.     TableViewController *tableViewController = [[TableViewController alloc]initWithStyle:UITableViewStylePlain];  
    8.     NSLog(@"here2");    
    9.     [self.window setRootViewController:tableViewController];   
    10.     // or [self.window.rootViewController.view addSubview:tableViewController.view];  
    11.     NSLog(@"here3");  
    12.     return YES;  
    13. }  
            结果:输出,界面显示tableviewController的界面
    1. 2014-09-20 16:40:14.135 Refer[3260:60b] ViewController : initWithCoder:  
    2. 2014-09-20 16:40:14.143 Refer[3260:60b] here1  
    3. 2014-09-20 16:40:14.146 Refer[3260:60b] <UIWindow: 0x16e5f570; frame = (0; 32480); hidden = YES; gestureRecognizers = <NSArray: 0x16e5fc10>; layer = <UIWindowLayer: 0x16e5f650>>  
    4. 2014-09-20 16:40:14.148 Refer[3260:60b] <ViewController: 0x16da9be0>  
    5. 2014-09-20 16:40:14.150 Refer[3260:60b] here2  
    6. 2014-09-20 16:40:14.153 Refer[3260:60b] here3   
    7. 2014-09-20 16:40:14.167 Refer[3260:60b] TableViewController : viewDidLoad  
           结果(当执行or里面的语句)输出,界面显示tableviewController的界面
    1. 014-09-20 16:43:21.707 Refer[3268:60b] ViewController : initWithCoder:  
    2. 2014-09-20 16:43:21.716 Refer[3268:60b] here1  
    3. 2014-09-20 16:43:21.718 Refer[3268:60b] <UIWindow: 0x16d88720; frame = (0; 32480); hidden = YES; gestureRecognizers = <NSArray: 0x16e7a1b0>; layer = <UIWindowLayer: 0x16d8c2b0>>  
    4. 2014-09-20 16:43:21.720 Refer[3268:60b] <ViewController: 0x16d8a170>  
    5. 2014-09-20 16:43:21.722 Refer[3268:60b] here2  
    6. 2014-09-20 16:43:21.731 Refer[3268:60b] ViewController : viewDidLoad // <span style="color:#cc0000;">因为调用到了它</span>  
    7. 2014-09-20 16:43:21.741 Refer[3268:60b] TableViewController : viewDidLoad  
    8. 2014-09-20 16:43:21.743 Refer[3268:60b] here3  
            分析用例5:当info.plist里面有值时,程序先加载storyboard中的对象,并创建之,之后创建AppDelegate的window,并且将初始控制器赋值给window的rootViewController,然后调用application:didFinishLaunchingWithOptions方法
    说明:
    1.window的rootViewController会覆盖windows上的子视图。
    2.如果使用storyboard的情况下,[self.window makeKeyAndVisible]方法会在方法application:didFinishLaunchingWithOptions结束后,隐式调用;当然也可以显示调用,window提前显示到了屏幕上。例如上面用例结果1,如果[self.window makeKeyAndVisible]显示写在 NSLog(@"here3");之前,则 输出“TableViewController : viewDidLoad” 在“here3”之前
    -------结论:
            使用storyboard的时候,先创建storyboard里面对象,和appDelegate的window,之后调用相关代理方法didFinish...,之后如果需要再调用[makeKeyAndVisible]
    --------------备注--------------
              a.关于Application如何查找对应的plist文件?  当一个target创建完,它自动关联了一个plist文件(名字一般是target.plist),如果我们修改了该plist文件名或者该文件被删除,导致target找不到该plist文件,则进入target info界面的时候要要求选择 plist文件,如下图:
     
    原文参见http://blog.csdn.net/houseq/article/details/38312281
  • 相关阅读:
    view如何被添加到window上并显示出来
    事件分发机制
    绘制机制
    setContentView
    消息机制——handler
    布局文件是如何被解析的?
    Xamarin.ios引用第三方SDK
    Xamarin.ios——First APP
    UITextView 文本垂直居中
    从NavigationController 下的UITableView中移除 header
  • 原文地址:https://www.cnblogs.com/HypeCheng/p/4662832.html
Copyright © 2011-2022 走看看