iOS 8應(yīng)用構(gòu)建細(xì)節(jié)挖掘之應(yīng)用啟動(dòng)流程
來源:易賢網(wǎng) 閱讀:869 次 日期:2015-01-22 09:47:55
溫馨提示:易賢網(wǎng)小編為您整理了“iOS 8應(yīng)用構(gòu)建細(xì)節(jié)挖掘之應(yīng)用啟動(dòng)流程”,方便廣大網(wǎng)友查閱!

本文遵循“署名-非商業(yè)用途-保持一致”創(chuàng)作公用協(xié)議

轉(zhuǎn)載請保留此句:太陽火神的美麗人生 - 本博客專注于 敏捷開發(fā)及移動(dòng)和物聯(lián)設(shè)備研究:iOS、Android、Html5、Arduino、pcDuino,否則,出自本博客的文章拒絕轉(zhuǎn)載或再轉(zhuǎn)載,謝謝合作。

24K 標(biāo)題黨!

不過內(nèi)容絕對夠細(xì)節(jié)而全面,僅針對啟動(dòng)流程這一小塊塊喲!

iOS 應(yīng)用啟動(dòng)流程,這個(gè)話題早在09年就非常熟悉,然而時(shí)隔多年,不知是否還熟悉,尤其 StoryBoard 的引入,那么下面就一起來看看吧,如果確實(shí)說明白了,給個(gè)評論,或哪里有不足,需要完善,也給個(gè)指點(diǎn)。

由于 Objective-C 是對 C 的擴(kuò)展,那么 main 函數(shù)理所當(dāng)然地繼承了程序入口的位置,而不像安卓,雖然它的程序入口點(diǎn)可能也是 main ,但那是掩埋在系統(tǒng)框架之內(nèi)根源處的,也或許叫別的名字,想了解可參考Android系統(tǒng)啟動(dòng)過程。

在 XCode 5.1.1 (2014-07-20 周日,此時(shí) iOS 8 已經(jīng)發(fā)布,但還未正式上架應(yīng)用,beta 3 據(jù)說已經(jīng)可以供開發(fā)者償鮮)中新建一個(gè)單視圖應(yīng)用 (Single View Application)。

XCode 工程中總有很多羅里巴山的文件,不過這也正是它先進(jìn)之處,控制權(quán)集中,撒出多個(gè)點(diǎn),來供開發(fā)者配置以改變應(yīng)用的運(yùn)行效果,或許用傻瓜式的應(yīng)用架構(gòu)方式更貼切一些,不過,像 iOS 這樣不開源的架構(gòu),是否長此以往,我們的后代人是否會(huì)真的變成傻瓜,對架構(gòu)內(nèi)部的程序藝術(shù)完全不了解,喪失了這種架構(gòu)能力了呢?!

切入主題,程序入口 main.m 文件如下:

#import <uikit uikit.h="">

#import "AppDelegate.h"

int main(int argc, char * argv[])

{

@autoreleasepool {

return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

}

}

</uikit>

main 函數(shù),和 C 語言中的一模一樣,帶兩個(gè)參數(shù),argc 是參數(shù)個(gè)數(shù),argv 是參數(shù)的字符串?dāng)?shù)組,或者叫列表也行。

上面兩行中 #import 是Objective-C 中新引入的和 #include 宏指令一樣的功能,引入其它頭文件。

之所以要引入這個(gè)新的指令來包含頭文件,是因?yàn)?#include 會(huì)存在重復(fù)引入的問題,即一個(gè)頭文件被引入多次,那么就可能定義了多個(gè)對象或變量,那是會(huì)出錯(cuò)的。

所以,在 C 中,會(huì)使用宏指令來判斷一個(gè)頭文件中的預(yù)定義宏名是否存在,不存在則在宏條件判斷中使用 #include 引入頭文件,否則不走這一宏分支,頭文件就不會(huì)被引入。

Availability.h 頭文件的精簡結(jié)構(gòu)如下,雖然在 -Prefix.pch 文件中是使用 #import 引入的該頭文件,但也不可掉以輕心,因?yàn)樵撐募€有可能在 C 代碼中使用 #include 引入,所以仍然加了 C 樣式的唯一引入宏結(jié)構(gòu):

#ifndef __AVAILABILITY__

#define __AVAILABILITY__

#include

#endif /* __AVAILABILITY__ */

</availabilityinternal.h>

這么麻煩地對頭文件進(jìn)行處理,真是浪費(fèi)時(shí)間,那么 #import 應(yīng)運(yùn)而生,不用擔(dān)心頭文件重復(fù)引入的問題。不過,別高興得太早,循環(huán)引用的問題,還是沒辦法解決的,這個(gè)就要用到另一個(gè) @class 來聲明類名的存在性以便在聲明文件中定義對象引用,而實(shí)際頭文件引入放在實(shí)現(xiàn)文件中。對于復(fù)雜些的邏輯,還是得靠你的整體把握能力來避勉循環(huán)引用:即 A 引入 B,B 引入 A 。

iOS 應(yīng)用程序中最常,也算是基本約定俗成的,要引入兩個(gè)框架:UIKit 和 Foundation。

而在 main.m 文件中,注釋掉 UIKit 的引入,程序也是會(huì)正常運(yùn)行的,因?yàn)椴⑽从玫?UIKit,只是程序模板默認(rèn)加上的,可能是其它類型應(yīng)用會(huì)用到吧,也許!

自動(dòng)釋放池,這里不作深入介紹,因?yàn)槲覀儺?dāng)前創(chuàng)建的應(yīng)用,都默認(rèn)是支持 ARC (自動(dòng)引用計(jì)數(shù) Automatic Reference Counting)的,所以使用這種配套的自動(dòng)釋放池方法。

@autoreleasepool {

1

}

早先的方式,已經(jīng)過時(shí),這種新的方式,也支持 MRC(手動(dòng)引用計(jì)數(shù) Manual Reference Counting)源文件的引入,只不過需要對源文件編譯部分進(jìn)行相應(yīng)參數(shù)設(shè)置,需加上

1

-fno-objc-arc

相反,在早期的 MRC 項(xiàng)目中,所使用的方式已經(jīng)過時(shí),當(dāng)下的 XCode 不會(huì)給你創(chuàng)建這樣的模板代碼,而且在用以 ARC 為主的工程時(shí),那個(gè)也不會(huì)得到預(yù)編譯的很好處理。如果確實(shí)需要的話,在 MRC 項(xiàng)目中引入 ARC 的源文件,在該 ARC 源文件的編譯選項(xiàng)中,輸入

1

-fobjc-arc

ARC 無非就是預(yù)編譯時(shí),由編譯器根據(jù)需要替你把需要加上的 MRC 中的相應(yīng)內(nèi)存管理的代碼加上去,而非真正的動(dòng)態(tài)內(nèi)存管理,即垃圾回收,所以它的效率和內(nèi)存占用率要優(yōu)質(zhì)得多。

接下來,

1

UIApplicationMain

將成為重點(diǎn)內(nèi)容,它就相當(dāng)于 MFC 中 WinMain 函數(shù)。

對于有窗體的應(yīng)用,它要呈現(xiàn)界面元素,并響應(yīng)用戶的操作,比如鼠標(biāo)、鍵盤、觸屏等用戶操作事件,以及移動(dòng)設(shè)備的各類傳感器事件等等。

這就要求帶窗體的應(yīng)用,要能夠循環(huán)查詢到這樣的事件,或許事件直接觸發(fā)可能會(huì)更快捷和節(jié)省資源,但那樣的后果是耦合性太強(qiáng)了。

所以,輪詢和事件觸發(fā)相結(jié)合,適當(dāng)?shù)姆峙?,才能達(dá)到預(yù)期的效果。事件由系統(tǒng)分發(fā)給每個(gè)或者移動(dòng)設(shè)備的當(dāng)前應(yīng)用,這需要由事件緩存池來完成,而每個(gè)應(yīng)用輪詢期自身得到的事件,或由外部置入事件池,或由內(nèi)部發(fā)生,得到這個(gè)事件后,再進(jìn)行觸發(fā),而將需要直接調(diào)用的回調(diào)函數(shù)進(jìn)行緩存,注意啦,在應(yīng)用內(nèi),變成了緩存事件回調(diào)函數(shù),而非事件本身,事件本身相當(dāng)于直接傳遞。由此就很好地解決了輪詢帶來的低效率和高資源占用與直接回調(diào)的耦合緊密等等弱點(diǎn)。

UIApplicationMain 函數(shù)有四個(gè)參數(shù):

1

UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

第一個(gè)和第二個(gè)參數(shù)是 C 程序體的傳入?yún)?shù),直接傳入,不做任何加工;

第三個(gè)參數(shù)是要?jiǎng)?chuàng)建的 iOS 應(yīng)用實(shí)例的類,該類是 UIApplication 或其子類,每個(gè)應(yīng)用僅此一個(gè);

第四個(gè)參數(shù)是要?jiǎng)?chuàng)建的應(yīng)用代理類,該類的功能其實(shí)是可以在應(yīng)用類中完成的,不過這種代理模式能很好地把這部分功能從應(yīng)用類中分離出來,這也是蘋果采用代理模式處理各種事件響應(yīng)的高明之處。開發(fā)人員只要按代理方法的要求進(jìn)行處理就可以了,對于統(tǒng)一規(guī)范預(yù)期工作任務(wù)很有幫助,不至于由于開發(fā)人員的疏忽,而把程序結(jié)構(gòu)搞得混亂。

下面就針對 UIApplicationMain 未指定代理類和指定代理類兩種情況對進(jìn)一步的應(yīng)用啟動(dòng)過程作以簡要敘述。

還有就是主窗體的來源,應(yīng)用類實(shí)例會(huì)從 xxx-Info.plist 中讀取相關(guān)配置信息。

其中 Main nib file base name 決定了從 nib 文件還是 StoryBoard 中獲取應(yīng)用的窗口信息,

1、如果是 nib,那么主窗口也從該文件中讀取,接下來,就可以從應(yīng)用代理中,給主窗口設(shè)置根視圖控制器;

如果 UIApplicationMain 的第四個(gè)參數(shù)應(yīng)用代理類為 nil 的話,應(yīng)用不知如何找到應(yīng)用代理類進(jìn)行實(shí)例化,它就會(huì)在這個(gè)主 nib 文件中尋找,尋找的規(guī)則是:

(這句話是錯(cuò)的,不是第四參為空,才從 nib 中取應(yīng)用代理,而是指定了主 nib ,就會(huì)默認(rèn)在這里找,如果找不到,再使用第四參)

a、主 nib 文件中的 File's Owner 是當(dāng)前應(yīng)用類,所以設(shè)成 UIApplication 或你指定的子類,然后在主 nib 中添加一個(gè)對象,設(shè)定它為應(yīng)用代理類,

并從 File's Owner 拉線到剛加入的設(shè)成應(yīng)用代理類的對象上,這時(shí)會(huì)彈出選項(xiàng),選擇 Outlets 下的 delegate,這樣就把應(yīng)用代理類關(guān)聯(lián)到了應(yīng)用類的代理引用上了。

以下 UIApplication.h 中 UIApplication 的聲明可以讓你明白應(yīng)用類與應(yīng)用代理類的關(guān)系是組合的方式,至于面向?qū)ο髲?fù)用機(jī)制的兩種方式繼承與組合,可以參見 繼承和組合:

NS_CLASS_AVAILABLE_IOS(2_0) @interface UIApplication : UIResponder <uiactionsheetdelegate>

{

@package

id <uiapplicationdelegate> _delegate;

</uiapplicationdelegate></uiactionsheetdelegate>

b、如果仍找不到的話,也即 File's Owner 所對應(yīng)的應(yīng)用類的 delegate 未指定應(yīng)用代理類,就會(huì)償試使用 UIApplicationMain 的第四個(gè)參數(shù)應(yīng)用代理類。

c、如果 主 nib 中 File's Owner 沒給應(yīng)用的 delegate 指定代理類,而且 UIApplicationMain 的第四個(gè)參數(shù)也為 nil,這時(shí)應(yīng)用一樣會(huì)啟動(dòng), nib 中的主窗口一樣會(huì)顯示,但沒有代理類,無法接收到應(yīng)用類的應(yīng)用生命周期的相關(guān)事件。

2、如果是 StoryBoard,主窗口就由應(yīng)用自動(dòng)創(chuàng)建,并將 StoryBoard 的第一個(gè)視圖控制器作為主窗口的根視圖控制器。

3、如果為空,則應(yīng)用就不管主窗口的事情了,由開發(fā)者自已來搞定,此時(shí)運(yùn)行,會(huì)在模擬器中看到黑屏應(yīng)用,即沒有窗口,當(dāng)然了,狀態(tài)欄作為窗口的一部分。

那么,主窗口從哪兒創(chuàng)建呢?這就涉及到應(yīng)用代理類了,因?yàn)榇翱谑强梢詣?dòng)態(tài)創(chuàng)建并指定的,而且窗口是可以有多個(gè)的,但主窗口只有一個(gè),并且只有一個(gè)處于可見狀態(tài)。

寫了一下午,邊測試,邊確認(rèn),邊構(gòu)思、組織語言與代碼,尚缺一些實(shí)際測試過程的截圖確認(rèn),這個(gè)后續(xù)再補(bǔ)上。

好像是缺點(diǎn)什么,當(dāng)時(shí)想到了,專注于某一個(gè)話題后再回到上面來俯視,發(fā)現(xiàn)忘記了......

回頭再說,想起來,隨時(shí)補(bǔ)充。

當(dāng)然了,這其中還包括,查到的與我這里話題相當(dāng)?shù)氖畮锥浅2诲e(cuò)的參考資料,先建個(gè)所有Chrome 的標(biāo)簽組吧,今天真的有點(diǎn)累了,該天再續(xù)。

更多信息請查看IT技術(shù)專欄

更多信息請查看網(wǎng)絡(luò)編程
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

2025國考·省考課程試聽報(bào)名

  • 報(bào)班類型
  • 姓名
  • 手機(jī)號
  • 驗(yàn)證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺 | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網(wǎng)安備53010202001879號 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號:hfpxwx
咨詢QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報(bào)警專用圖標(biāo)