亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

詳解iOS應用程序的啟動過程

2020-07-26 03:25:24
字體:
來源:轉載
供稿:網友

關鍵步驟
一個程序從main函數開始啟動。

復制代碼 代碼如下:

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

可以看到main函數會調用UIApplicationMain函數,它的四個參數的意思是:

  • argc: 代表程序在進入main函數時的參數的個數。默認為1。
  • argv: 代表包含的各個參數。默認為程序的名字。
  • principalClassName: UIApplication或者它的子類的名字, 如果傳入的是nil, 則表示UIApplication的名字, 即@"UIApplication"。
  • delegateClassName: UIApplication的代理的名字。

在UIApplicationMain函數中,根據傳入的UIApplication名稱和它的代理的名稱,會主要做下面的事情:

  • 根據傳入的名稱創建UIApplication對象。
  • 根據傳入的代理名稱創建UIApplication代理對象。
  • 開啟事件循環(如果不進行循環,那么在main函數結束后程序就結束了。要保證程序創建后可以一直存在)。
  • 解析Info.plist文件:

會在Info.plist文件里查找Main storyboard file base name這個Key對應的Value是否有值。如果有值,則表示之后會通過Storyboard加載控制器,AppDelegate會接收到didFinishLaunchingWithOptions消息(程序啟動完成的時候),此時Storyboard會進行一系列的加載操作(后面會具體說);如果沒有值,則不會通過Storyboard加載控制器,接著AppDelegate會接收到didFinishLaunchingWithOptions消息(程序啟動完成的時候),在這個時候需要我們通過代碼的方式加載控制器。

注意Info.plist中Main storyboard file base name這個Key并不是真正的Key,而是蘋果為了增強可讀性才這樣寫的,真正的Key為UIMainStoryboardFile(可以通過Info.plist文件的源代碼查看)。
這就是在想要用代碼方式創建控制器而不是Storyboard創建控制器的時候為什么先要將Main Interface設置為空白,這樣在解析Info.plist文件的時候才會知道不通過Storyboard創建控制器。
由此可以知道,解析Info.plist文件這一操作主要是看我們用的是Storyboard方式加載還是代碼的方式加載。默認Main storyboard file base name為Main,也就是通過Storyboard方式加載控制器。
現在具體分析一下,通過Storyboard方式加載控制器和代碼方式加載控制器。

通過Storyboard
通過Storyboard,主要做了下面的事情(這些事情不需要我們做,是系統自動完成的,在程序啟動完成的時候):

創建窗口。

創建一個UIWindow的實例用來顯示界面。

設置窗口的根控制器。

根據Storyboard的設置,創建一個控制器。
并且設置這個控制器為之前創建的window的根控制器。
顯示窗口。(相當于后面提到的makeKeyAndVisible)

設置self.window可見并且設置UIApplication的keyWindow。

在這一步中將根控制器的view添加到window上。

通過代碼方式
通過代碼的方式,需要我們在didFinishLaunchingWithOptions方法中進行加載控制器的相關操作。

復制代碼 代碼如下:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    UIViewController *viewController = [[UIViewController alloc] init];
    self.window.rootViewController = viewController;
    // 此時根控制器的view還沒有加到self.window上
    [self.window makeKeyAndVisible];
    // 此時根控制器的view加到self.window上
    return YES;
}


其實這里所做和系統所做是一樣的。(相當于系統的做法)

首先創建窗口,得到一個正確的UIWindow實例對象用來顯示界面。(self.window是系統自帶的屬性)

接著設置窗口的根控制器。

不再根據Storyboard中的設置加載,此時需要我們自己創建控制器。
設置這個控制器為self.window的根控制器。
注意這個時候根控制器的view還沒有加到self.window上,當窗口要顯示的時候,才會把窗口的根控制器的view添加到窗口。(可以輸出self.window.subViews來驗證)
顯示窗口。

復制代碼 代碼如下:

[self.window makeKeyAndVisible]實際上做了下面的事:

首先,將self.window設置為UIApplication的keyWindow,這么做是方便我們以后查看UIApplication的主窗口是哪一個。

接著,讓self.window可見,相當于執行的代碼是:

復制代碼 代碼如下:

self.window.hidden = NO;

這么做的原因是self.window默認hidden = YES,所以需要讓其顯示出來。

那么既然makeKeyAndVisible執行的是以上的操作,實際上將[self.window makeKeyAndVisible]替換為self.window.hidden = NO,那么界面也會正常顯示出來,因為makeKeyAndVisible內部就是這么做的。但是此時并沒有設置UIApplication的keyWindow,為了以后方便訪問,還是用makeKeyAndVisible更好一點。

經過這一步,界面將要顯示,此時根控制器的view會加到self.window上以正常顯示。

這里有一點要注意:

系統創建的AppDelegate自帶一個屬性位于.h文件中:

復制代碼 代碼如下:

@property (strong, nonatomic) UIWindow *window;

當用Storyboard的方式加載控制器,在應用啟動完成的時候(didFinishLaunchingWithOptions)需要一個UIWindow的實例來顯示界面,所以Apple提供了這個window屬性。系統根據storyboard自動創建一個window,然后將window賦值給這個window屬性,以保證完成之后的工作。

當用代碼的方式加載控制器,同樣的,首先也需要一個UIWindow的實例來顯示界面,因為不使用Storyboard所以這次要我們自己創建window。此時有兩種做法,第一種是在didFinishLaunchingWithOptions方法中創建一個UIWindow對象:

復制代碼 代碼如下:

UIWindow *myWindow = [[UIWindow alloc] initWithFrame:...];

但是如果用這種方法運行程序會發現界面依然無法顯示出來,因為此時myWindow是一個局部變量,當didFinishLaunchingWithOptions方法執行完畢這個變量就會銷毀。所以更好的辦法是直接使用系統提供的window屬性:
復制代碼 代碼如下:

self.window = [[UIWindow alloc] initWithFrame:...];

之前的例子也是這么做的。

另外,仔細觀察會發現這個window屬性的修飾符是strong,而不是weak。想想之前使用weak來修飾一個控件是因為這個控件會被加到一個view中,這個view的subViews數組會有強引用指向控件,所以用weak是沒有問題的?,F在這種情況,因為window控件不會被加到其他view中,即沒有其他的強指針指向這個對象,所以在創建的時候需要將修飾符設置成strong以保證創建出的window不會被銷毀。(Apple創建的window屬性的修飾符是strong)

UIWindow的補充
window是有層級的,并且可以有多個window同時存在。比如:狀態欄就是一個window,鍵盤也是一個window。

可以通過設置UIWindow的對象的windowLevel屬性來調整層級。

self.window.windowLevel = UIWindowLevelStatusBar;
window共有三種等級:UIWindowLevelNormal,UIWindowLevelStatusBar UIWindowLevelAlert。如果三種等級同時出現在屏幕上,那么alert在最上面,statusBar在中間,normal則在最下面。

注意:如果一個程序中有多個window,控制器默認會把狀態欄隱藏。

解決辦法:關閉控制器對狀態欄的控制,(為Info.plist增加View controller-based status bar appearance這個key并設置為NO)這樣這些window以及狀態欄就可以按層級關系正常顯示。

概覽
這里PY為前綴名:

1.先執行main函數,main內部會調用UIApplicationMain函數

2.UIApplicationMain函數里面做了什么事情:

(1)創建UIApplication對象

(2)創建UIApplication的delegate對象―亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

欧美午夜电影在线| 国产亚洲aⅴaaaaaa毛片| 久久亚洲私人国产精品va| 亚洲人成网站999久久久综合| 国产在线精品自拍| 亚洲第一区中文字幕| 欧美高清理论片| 日本91av在线播放| 国产亚洲美女久久| 美女国内精品自产拍在线播放| 日韩中文av在线| www.久久久久久.com| 日韩h在线观看| 日韩在线观看免费高清完整版| 亚洲人成电影网站| 日本成人精品在线| 一区二区三区高清国产| 欧美成人免费小视频| 欧美国产高跟鞋裸体秀xxxhd| 欧美俄罗斯性视频| 日韩在线免费观看视频| 欧美极品欧美精品欧美视频| 国产精品www色诱视频| 亚洲视频在线观看视频| 国产精品极品尤物在线观看| 97精品一区二区视频在线观看| 国产免费一区二区三区在线能观看| 欧美激情视频免费观看| 免费不卡欧美自拍视频| 亚洲网址你懂得| 欧美丰满老妇厨房牲生活| 一本色道久久88精品综合| 亚洲自拍高清视频网站| 国产一区二区视频在线观看| 福利微拍一区二区| 久久精品国产视频| 日韩精品免费在线视频观看| 精品美女久久久久久免费| 国产主播喷水一区二区| 日韩av在线免费观看| 国产亚洲a∨片在线观看| 亚洲aⅴ日韩av电影在线观看| 久久久久久九九九| 在线观看成人黄色| 亚洲人免费视频| 在线观看国产精品日韩av| 久久久久国色av免费观看性色| 国产精品九九久久久久久久| 色婷婷**av毛片一区| 欧美中文字幕精品| 欧美日韩国内自拍| www日韩中文字幕在线看| 久久国产精品99国产精| 日韩性xxxx爱| 欧美午夜女人视频在线| 奇米成人av国产一区二区三区| 国产精品日本精品| 国产精品第三页| 国产99在线|中文| 国产精品国产三级国产aⅴ9色| 精品久久久久久亚洲国产300| 2019中文字幕在线观看| 亚洲视频视频在线| 亚洲精品丝袜日韩| 日韩大胆人体377p| 国产原创欧美精品| 亚洲视频网站在线观看| 亚洲精品久久久久久久久久久久| 色噜噜亚洲精品中文字幕| 国产美女直播视频一区| 国产精品国产自产拍高清av水多| 日韩中文字幕在线视频播放| 欧美最猛黑人xxxx黑人猛叫黄| 91chinesevideo永久地址| 亚洲一区二区三区在线视频| 91成人精品网站| 欧美华人在线视频| 亚洲在线免费看| 日韩成人免费视频| 日韩av片永久免费网站| 欧美理论电影在线播放| 色噜噜狠狠色综合网图区| 欧美日韩激情小视频| 久久久久久97| 国产一区二区美女视频| 国产精品视频网| 精品久久香蕉国产线看观看gif| 97在线免费观看视频| 国产精品自产拍在线观| 亚洲字幕在线观看| 欧美专区在线播放| 色偷偷av亚洲男人的天堂| 亚洲第一福利视频| 亚洲精品久久久久久久久| 日韩高清免费在线| 成人亚洲欧美一区二区三区| 午夜精品一区二区三区视频免费看| 懂色aⅴ精品一区二区三区蜜月| 欧美成人精品一区二区| 欧美在线精品免播放器视频| 57pao成人国产永久免费| 国产精品一区二区三区久久久| 日韩电影免费观看在线观看| 久久精品99国产精品酒店日本| 粉嫩老牛aⅴ一区二区三区| 性色av一区二区三区免费| 日韩欧美视频一区二区三区| 97人人模人人爽人人喊中文字| 精品美女久久久久久免费| 亚洲人在线观看| 精品无码久久久久久国产| 日韩精品免费综合视频在线播放| 亚洲性视频网站| 久久综合伊人77777蜜臀| 欧美极品少妇xxxxⅹ免费视频| 亚洲国产中文字幕在线观看| 欧美精品免费看| 亚洲免费视频一区二区| www.欧美精品| 久久久国产一区二区| 亚洲第一免费播放区| 91中文字幕在线观看| 国产精品久久久久久中文字| 久久精品成人欧美大片古装| 91亚洲精品久久久| 欧美成人手机在线| 亚洲一区二区在线| 国产午夜精品一区二区三区| 国产香蕉一区二区三区在线视频| 亚洲欧美一区二区三区情侣bbw| 日本三级韩国三级久久| 国产日韩欧美在线| 国产精品激情av在线播放| 欧美激情精品久久久久久| 久久久久久久国产精品| 成人激情视频免费在线| 搡老女人一区二区三区视频tv| 国产v综合ⅴ日韩v欧美大片| 亚洲综合色激情五月| 日韩在线视频播放| 国产精品入口日韩视频大尺度| 久久久999精品免费| 欧美日韩中文字幕在线| 久久99精品久久久久久噜噜| 国产香蕉一区二区三区在线视频| 成人欧美一区二区三区黑人孕妇| 日韩av中文在线| 国内外成人免费激情在线视频| 亚洲全黄一级网站| 日韩av最新在线观看| 91久久在线视频| 久久久久久久久久婷婷| 久久久久久久999| 久久综合久久美利坚合众国| 国产日产欧美精品| 91精品视频一区| 欧洲亚洲妇女av| 在线成人一区二区| 亚洲精品在线91| 亚洲一级一级97网| 国产精品私拍pans大尺度在线| 91精品视频在线免费观看| 欧美视频专区一二在线观看| 色综合视频网站|