在上文 iOS —— 視圖,視圖控制器和窗口 中,我們大概描述視圖,視圖控制器和窗口這是三個開發中繞不開的東西。
接下來我們再來看一下程序的啟動流程,然后修改一下啟動流程的一些步驟,自定義啟動窗口。
一、iOS 程序簡易啟動流程
一.1、找到main.m文件,執行 main 函數 里面的 UIApplicationMain 方法,創建UIApplication對象,并設置UIApplication的代理.
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
/**
第三個參數:UIApplication或子類對象 ,為nil則默認為自帶的 UIApplication
第四個參數:第三個參數的類的名稱
*/
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
一.2、UIApplicationMain會開啟了一個事件循環.(主運行循環,死循環:保證應用程序不退出)
Discussion
This function instantiates the application object from the principal class and instantiates the
delegate (if any) from the given class and sets the delegate for the application.
It also sets up the main event loop, including the application’s run loop,
and begins processing events. If the application’s Info.plist file specifies a main nib file to be loaded,
by including the NSMainNibFile key and a valid nib file name for the value, this function loads that nib file.
一.4、加載info.plist文件,在Main storyboard file base name一欄檢查是否有指定 storyboard 文件的名稱
判斷info.plist當中有沒有storyboard (比如Main.storyboard)
- 如果沒有,那么就把待會啟動程序就是一片黑色,黑色就是窗口的顏色、
- 如果有,那么就把storyboard里面箭頭指向的控制器設置窗口的控制器(如果該控制器不是箭頭指向的控制器,那么運行加載出來的依然是一片黑,所以箭頭指向很重要)
一.5、應用程序啟動完畢.(通知代理應用程序啟動完畢)
二、自定義啟動窗口
先有盤古開天,后有天地。
在iOS程序的世界的世界里,先有UIWindows,再有頁面。
新建程序自帶的Main.storyboard是為了我們方便編碼測試,但是開發中為了讓我們對程序有更全面的控制,我們經常不用系統的Main.storyboard,而是用我們的UIWindow。
用自己的UIWindow,就是要把 AppDelegate.m的里面把系統幫我們也做出來,簡單分為如下三步:
1、創建窗口(窗口必須有指定的 根控制器 )
2、創建根控制器,窗口指向根控制器
3、顯示
簡單代碼
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//1.創建窗口
// self.window,在AppDelegate.h文件里面是自帶強引用,必須強引用
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
//2.一個窗口必須得有根控制器(設置窗口的根控制器)
// ios9智慧窗口如果不設置大小,那么默認就是屏幕大小
UIViewController *vc = [[UIViewController alloc] init];
vc.view.backgroundColor = [UIColor redColor]; //設置控制器的背景為紅色
self.window.rootViewController = vc;
// 顯示
[self.window makeKeyAndVisible];
return YES;
}
@end
.
效果
.
.
通過上面的圖文,我們知道第一第二步沒什么特別的,但是第三步的 makeKeyAndVisible 方法內部做了挺多事情的,比如如下這些:
makeKeyAndVisible 做了如下這么幾件事情:
1.設置應用程序的主窗口
2.讓窗口顯示,把窗口 hidden = NO (默認是YES),
顯示過程當中,把窗口的 根控制器的view 添加到窗口上 相當于 [self.window addsubView:rootViewCotroller.view]
我們再看一份代碼,把makeKeyAndVisible做的事情分幾次完成
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//1.創建窗口
// self.window,在AppDelegate.h文件里面是自帶強引用,必須強引用
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor yellowColor];
//2.一個窗口必須得有根控制器(設置窗口的根控制器)
// ios9智慧窗口如果不設置大小,那么默認就是屏幕大小
UIViewController *vc = [[UIViewController alloc] init];
vc.view.backgroundColor = [UIColor redColor]; //設置控制器的背景為紅色
// 往控制器上添加一個按鈕
UIButton *button =[[UIButton alloc]initWithFrame:CGRectMake(10, 30, 50, 100)];
button.backgroundColor = [UIColor greenColor];
[vc.view addSubview:button];
NSLog(@"keyWindow 主窗口 第一次 %@",[UIApplication sharedApplication].keyWindow);
NSLog(@"subviews 窗口的子View 第一次 %@",self.window.subviews);
NSLog(@"hidden狀態 第一次 %@\n",self.window);
self.window.rootViewController = vc;
NSLog(@"keyWindow 主窗口 第二次 %@",[UIApplication sharedApplication].keyWindow);
NSLog(@"subviews 窗口的子View 第二次 %@",self.window.subviews);
NSLog(@"hidden狀態 第二次 %@\n",self.window);
[self.window makeKeyWindow];
NSLog(@"keyWindow 主窗口 第四次 %@",[UIApplication sharedApplication].keyWindow);
NSLog(@"subviews 窗口的子View 第四次 %@",self.window.subviews);
NSLog(@"hidden狀態 第四次 %@\n",self.window);
self.window.hidden = NO;
NSLog(@"hidden 狀態 設置后 %@",self.window);
NSLog(@"keyWindow 主窗口 第三次 %@",[UIApplication sharedApplication].keyWindow);
NSLog(@"hidden狀態 第三次 %@\n",self.window);
return YES;
}
@end
.
.
根據這份代碼生成的log
keyWindow 主窗口 第一次 (null)
subviews 窗口的子View 第一次 (
)
hidden狀態 第一次 <UIWindow: 0x7fefab7077d0; frame = (0 0; 375 667); hidden = YES; gestureRecognizers = <NSArray: 0x61800004d3b0>; layer = <UIWindowLayer: 0x618000220700>>
keyWindow 主窗口 第二次 (null)
subviews 窗口的子View 第二次 (
)
hidden狀態 第二次 <UIWindow: 0x7fefab7077d0; frame = (0 0; 375 667); hidden = YES; gestureRecognizers = <NSArray: 0x61800004d3b0>; layer = <UIWindowLayer: 0x618000220700>>
keyWindow 主窗口 第四次 <UIWindow: 0x7fefab7077d0; frame = (0 0; 375 667); hidden = YES; gestureRecognizers = <NSArray: 0x61800004d3b0>; layer = <UIWindowLayer: 0x618000220700>>
subviews 窗口的子View 第四次 (
)
hidden狀態 第四次 <UIWindow: 0x7fefab7077d0; frame = (0 0; 375 667); hidden = YES; gestureRecognizers = <NSArray: 0x61800004d3b0>; layer = <UIWindowLayer: 0x618000220700>>
hidden 狀態 設置后 <UIWindow: 0x7fefab7077d0; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x61800004d3b0>; layer = <UIWindowLayer: 0x618000220700>>
keyWindow 主窗口 第三次 <UIWindow: 0x7fefab7077d0; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x61800004d3b0>; layer = <UIWindowLayer: 0x618000220700>>
hidden狀態 第三次 <UIWindow: 0x7fefab7077d0; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x61800004d3b0>; layer = <UIWindowLayer: 0x618000220700>>
嗯我想已經很全面了。
注意點:
1、如果hidden狀態為YES,那么窗口無法顯示,即使已經makeKeyWindow
2、如果設置了makeKeyWindow,那么就代表已經給 UIWindows 設置跟控制器了(當前前提是你前面已經[vc.view addSubview:button]),但是如果設置hidden為NO依然不行,但是確實已經設置上去了。
所以: makeKeyAndVisible = hidden + makeKeyWindow
.
.
.
本篇完。