您的位置:首页 > 移动开发

iOS:App启动过程详解(相关资源xib等的访问)

2014-07-31 10:06 399 查看
--------------xcode4.2以前(用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)--------------



--.先执行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------------

问题:上叙7~10猜想成分太大了,而且application:didFinishLaunchingWithOptions 跟加载storyboard文件顺序交叉了,到底它们实际执行顺序是什么?
**用例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中的对象,并创建之,之后创建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文件,如下图:


b.UIWindow里面有UIScreen,属性,但是创建UIWindow还是用的[UIScreen mainScreen]。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐