iOS:App启动过程详解(不同方式)

--------------xcode4.2以前(用xib)--------------xib创建

应用程序开始的时候没有指定和创建delegete,是通过一个xib文件来创建(MainWindow.xib)

int main(int argc, char *argv[]) {            
     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];    
     int retVal = UIApplicationMain(argc, argv, nil, nil);    
     [pool release];    
     return retVal;    
 } 
--程序开始-->创建UIApplication实例-->查看应用程序的 Info.plist -->根据Main nib file base name属性,加载xib文件,创建相应类。程序启动调用相应代理方法,详见如下:


其中File‘s Owner为UIApplication,它的delegate为第三个图标,Button_FunAppDelegate,剩下俩个为Window和初始控制器(delegate类的属性)。通过创建xib,实例化应用程序相应的Delegate类以及Window、控制器。

--应用程序代理类通过xib文件创建,他的相应属性UIWindow、根控制器等也可包括在xib中

--该xib为《View-based Application》模版,其中有控制器对象。

--《Window-based Application》和《View-based Application》 区别在于有没有第四个图标Button_FunViewController,以及代码 “self.window.rootViewController = self.viewController” 或者“[self.window addSubview: self.viewController.view];”的有无。

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

--------------xcode4.2以后(without storyboard)--------------代码手动

应用程序开始的时候指定了delegete,之后delegate类被创建。

int main(int argc, char *argv[]) {    
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    [pool release];
    return retVal;
}
程序开始-->创建UIApplication实例-->创建Delegate类,赋给uiApplication的delegate属性,程序启动后调用相应代理方法。

-- 应用程序Info.plist文件不再需要Main nib file base name属性,也不再需要“MainWindow.xib”。

--应用程序代理类不通过xib文件创建,他的相应属性UIWindow、根控制器类等代码创建。

--模板变为《Empty Application》和《Single View Application》

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{	
	self.window= [[UIWindowalloc] initWithFrame:[[UIScreenmainScreen] bounds]];
	//self.viewController= [[<app>ViewController alloc] init];
        //self.window.rootViewController = self.viewController;
	[self.windowmakeKeyAndVisible];
 return YES;
}
------- ------- xcode4.2以后(with storyboard) ------- -------storyboard创建

--注:上图是without storyboarding的方式,借鉴
--.先执行main函数,main内部会调用UIApplicationMain函数
--.UIApplicationMain函数里面做了什么事情:
1.调用UIApplicationMain()函数;
2.创建UIApplication对象;
3.创建UIApplication的delegate对象-----XXAppDelegate;
4.加载Info.plist文件,读取最主要storyboard文件的名称;
5.UIApplication开启一个消息循环
* 每监听到对应的系统事件时,就会通知MJAppDelegate;
6.UIApplication调用相关代理方法;
------------我是分割线------------
那么在6之前UIApplication调用相关代理方法之前,4里面创建storyboard里面做了哪些事情?
------ ------end ------------
      ** 用例1**:不使用storyboard,程序启动后进入application:didFinishLaunchingWithOptions方法,该方法内部什么都不实现
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.  
    return YES;
}
      结果:程序启动,屏幕一片漆黑。
      用例1分析:程序启动,didFinishLaunchingWithOptions方法里没有加载任何视图(还有window原因,见下面用例)。
      ** 用例2**:不使用storyboard,程序启动后进入application:didFinishLaunchingWithOptions方法,该方法内部创建添加需要显示的内容。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
   
    TableViewController *tableViewController = [[TableViewController alloc]initWithStyle:UITableViewStylePlain];    
    [self.window addSubview:tableViewController.view];    
    [self.window makeKeyAndVisible];
    return YES;
}
      结果:程序启动,屏幕一片漆黑
      ** 用例3**:不使用storyboard,程序启动后进入application:didFinishLaunchingWithOptions方法,该方法内部创建UIWindow,并创建添加需要显示的内容。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
    TableViewController *tableViewController = [[TableViewController alloc]initWithStyle:UITableViewStylePlain];    
    [self.window addSubview:tableViewController.view];    
    [self.window makeKeyAndVisible];
    return YES;
}
       结果:程序启动,显示tableviewController的视图,正常。
        用例2+用例3分析:当不用storyboard的时候,AppDelegate被创建完之后,它的window属性为空,需要手动创建之。然后再用它
      ** 用例4**:使用storyboard,程序启动后进入application:didFinishLaunchingWithOptions方法,该方法内部创建添加需要显示的内容
        (备注:storyboard里面初始化的控制器为ViewController,并且在相关方法输出了_cmd)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
   
    NSLog(@"here1");
    NSLog(@"%@",self.window);
    TableViewController *tableViewController = [[TableViewController alloc]initWithStyle:UITableViewStylePlain];  
    NSLog(@"here2");  
    [self.window addSubview:tableViewController.view];
    NSLog(@"here3");
    return YES;
}
        结果:输出,界面显示ViewController的界面
2014-09-20 16:30:22.066 Refer[3253:60b] ViewController : initWithCoder:
2014-09-20 16:30:22.074 Refer[3253:60b] here1
2014-09-20 16:30:22.077 Refer[3253:60b] <UIWindow: 0x14db9020; frame = (0 0; 320 480); hidden = YES; gestureRecognizers = <NSArray: 0x14db9cb0>; layer = <UIWindowLayer: 0x14dbb910>>
2014-09-20 16:30:22.079 Refer[3253:60b] here2
2014-09-20 16:30:22.091 Refer[3253:60b] TableViewController : viewDidLoad
2014-09-20 16:30:22.095 Refer[3253:60b] here3
2014-09-20 16:30:22.104 Refer[3253:60b] ViewController : viewDidLoad
        分析用例4:tableviewController的界面不显示,可能是被viewController界面覆盖了,还是某种原因。
     ** 用例5**:使用storyboard,程序启动后进入application:didFinishLaunchingWithOptions方法,该方法内部创建添加需要显示的内容
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
   
    NSLog(@"here1");
    NSLog(@"%@",self.window);
    NSLog(@"%@",self.window.rootViewController);
    TableViewController *tableViewController = [[TableViewController alloc]initWithStyle:UITableViewStylePlain];
    NSLog(@"here2");  
    [self.window setRootViewController:tableViewController]; 
    // or [self.window.rootViewController.view addSubview:tableViewController.view];
    NSLog(@"here3");
    return YES;
}
        结果:输出,界面显示tableviewController的界面
2014-09-20 16:40:14.135 Refer[3260:60b] ViewController : initWithCoder:
2014-09-20 16:40:14.143 Refer[3260:60b] here1
2014-09-20 16:40:14.146 Refer[3260:60b] <UIWindow: 0x16e5f570; frame = (0 0; 320 480); hidden = YES; gestureRecognizers = <NSArray: 0x16e5fc10>; layer = <UIWindowLayer: 0x16e5f650>>
2014-09-20 16:40:14.148 Refer[3260:60b] <ViewController: 0x16da9be0>
2014-09-20 16:40:14.150 Refer[3260:60b] here2
2014-09-20 16:40:14.153 Refer[3260:60b] here3 
2014-09-20 16:40:14.167 Refer[3260:60b] TableViewController : viewDidLoad
       结果(当执行or里面的语句)输出,界面显示tableviewController的界面
014-09-20 16:43:21.707 Refer[3268:60b] ViewController : initWithCoder:
2014-09-20 16:43:21.716 Refer[3268:60b] here1
2014-09-20 16:43:21.718 Refer[3268:60b] <UIWindow: 0x16d88720; frame = (0 0; 320 480); hidden = YES; gestureRecognizers = <NSArray: 0x16e7a1b0>; layer = <UIWindowLayer: 0x16d8c2b0>>
2014-09-20 16:43:21.720 Refer[3268:60b] <ViewController: 0x16d8a170>
2014-09-20 16:43:21.722 Refer[3268:60b] here2
2014-09-20 16:43:21.731 Refer[3268:60b] ViewController : viewDidLoad // <span style="color:#cc0000;">因为调用到了它</span>
2014-09-20 16:43:21.741 Refer[3268:60b] TableViewController : viewDidLoad
2014-09-20 16:43:21.743 Refer[3268:60b] here3
        分析用例5: 当info.plist里面有值时,程序先加载storyboard中的对象,并创建之,之后根据程序入口(辣个箭头)创建window,并处理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]
----------------------------------
--------------总结--------------
不管什么方式xib、代码手动、还是storyboard,其实做的事情一样,只是途径不一样,都是创建了window和根控制器,并赋值rootViewController,并显示窗口
--------------备注--------------
          a.关于Application如何查找对应的plist文件?  当一个target创建完,它自动关联了一个plist文件(名字一般是target.plist),如果我们修改了该plist文件名或者该文件被删除,导致target找不到该plist文件,则进入target info界面的时候要要求选择 plist文件,如下图:
          b.UIWindow里面有UIScreen,属性,但是创建UIWindow还是用的[UIScreen mainScreen]。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值