1. 程式人生 > >iOS/iPhone 程式檔案目錄結構以及啟動流程

iOS/iPhone 程式檔案目錄結構以及啟動流程

要想清晰的理解IOS應用程式的啟動過程,毫無疑問需要深入瞭解一下ios應用程式的檔案系統。一個ios應用程式都有一個屬於自己沙盒(sandbox),應用沙盒就是檔案系統目錄,並且與檔案系統的其他部分隔離。應用必須待在自己的沙盒裡,應用既不能訪問其他應用的沙盒,其他應用也不能訪問該沙盒。

         應用沙盒包含多個目錄:

         1.應用程式包(application bundle):包含所有的資原始檔和可執行檔案,並且是隻讀檔案目錄。

         注意:每個應用程式可以有多個程式包,但是隻能有一個主程式包,即包含應用程式程式碼的程式包。當用戶啟動應用程式的時候,應用程式會在主程式包中尋找即刻要用到的程式碼和資源,並將其載入到記憶體。然後它可以根據需要動態(並延時)載入主程式包或者叢屬程式包中的程式碼和資源。應用程式可以用NSBundle 和Core Foundation 的CFBundleRef(在過程化的語言中使用)定位程式包中的資源。在Objective-C中,首先要獲得一個NSBundle例項,它和某個物理程式包對應。如需獲得應用程式主程式包,則應呼叫mainBundle類方法。然後呼叫NSBundle的其他方法,傳入檔名、副檔名以及(可選)程式包子目錄,這些方法將會返回程式包資源的路徑。有了資源路徑,您就可以使用恰當的類將其載入到記憶體。程式碼案例有:

  1. NSString *str=[[NSBundle mainBundle]pathForResource:@"example" ofType:@"png"];  
即可返回應用程式包中保含的example.png檔案的路徑。你可以使用str來對example.png進行操作。

         2.偏好設定檔案(Library/Preferences/):存放所有的偏好設定。通過NSUserDefaults類可以讀取寫入該檔案,同時可以作為應用的預設啟動設定,即應用的setting會在該目錄中查詢應用的設定資訊。

         3.臨時檔案(tmp/):用於儲存程式執行時所需的臨時資料,使用完畢後的臨時資料對應的檔案將從該目錄下刪除。同時,應用結束時也可能會清除該目錄下的檔案。在程式執行時可以通過方法NSTemporaryDirectory可以的得到該沙盒下tmp目錄的全路徑。

         4.應用執行時保留的資料(Documents/):儲存應用執行時生成的需要保留的資料。該檔案對於在裝置發生故障時,通過ituns同步裝置備份該目錄,從而可以恢復應用的資料。

         5.儲存應用執行時生成的需要保留的資料(Library/Caches):與4的不同之處時ituns同步不能備份該目錄。因為該快取資料的體積比較大,會延長同步裝置所需的時間。但是如果資料來源在別處(例如,網路的伺服器),那麼可以通過將資料儲存在該目錄。當用戶需要恢復裝置,可以從伺服器下載這些資料。

          可以總結一下,Library/Preferences/、Documents/ 下的檔案時可以通過iTuns同步裝置時進行備份目錄,而tmp/、Documents/是不能備份的。用表格表示如下:

目錄

描述

<Application_Home>/AppName.app

這是程式包目錄,包含應用程式的本身。由於應用程式必須經過簽名,所以您在執行時不能對這個目錄中的內容進行修改,否則可能會使應用程式無法啟動。

在iPhone OS 2.1及更高版本的系統,iTunes不對這個目錄的內容進行備份。但是,iTunes會對在App Store上購買的應用程式進行一次初始的同步。

<Application_Home>/Documents/

您應該將所有的應用程式資料檔案寫入到這個目錄下。這個目錄用於儲存使用者資料或其它應該定期備份的資訊。有關如何取得這個目錄路徑的資訊,請參見部分。

iTunes會備份這個目錄的內容。

<Application_Home>/Library/Preferences

這個目錄包含應用程式的偏好設定檔案。您不應該直接建立偏好設定檔案,而是應該使用類或CFPreferences API來取得和設定應用程式的偏好,詳情請參見部分。

iTunes會備份這個目錄的內容。

<Application_Home>/Library/Caches

這個目錄用於存放應用程式專用的支援檔案,儲存應用程式再次啟動過程中需要的資訊。您的應用程式通常需要負責新增和刪除這些檔案,但在對裝置進行完全恢復的過程中,iTunes會刪除這些檔案,因此,您應該能夠在必要時重新建立。您可以使用 部分描述的介面來獲取該目錄的路徑,並對其進行訪問。

在iPhone OS 2.2及更高版本,iTunes不對這個目錄的內容進行備份。

<Application_Home>/tmp/

這個目錄用於存放臨時檔案,儲存應用程式再次啟動過程中不需要的資訊。當您的應用程式不再需要這些臨時檔案時,應該將其從這個目錄中刪除(系統也可能在應用程式不執行的時候清理留在這個目錄下的檔案)。有關如何獲得這個目錄路徑的資訊,請參見部分。

在iPhone OS 2.1及更高版本,iTunes不對這個目錄的內容進行備份。

         上面介紹了沙盒的檔案系統結構,下面繼續講應用程式包中檔案,這裡面的資原始檔以及可執行檔案是程式工程開發時產生的。它基本上包含了:         

         1. .pch:預編譯標頭檔案,win32裡經常會碰到,這裡也有,包含了常用的標頭檔案。          2. .plist:包含了專案自身的特性,比如說專案名稱,預設載入的nib file,版本等。          3..xib:程式的資原始檔。用於簡化編碼過程,提高開發效率。          4. main.m:iOS應用程式的入口,類似於C/C++中的main函式。           到了這裡,基本就可以開始應用程式具體的啟動過程了。          在main.m檔案中,
  1. <span style="font-size:14px;">int main(int argc, char *argv[]) {  
  2.     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];  
  3.     <strong>int retVal = UIApplicationMain(argc, argv, nil, nil);</strong>  
  4.     [pool release];  
  5.     return retVal;  
  6. }  
  7. </span>  

main函式仍然是程式的入口函式,其中argc、argv為執行程式的支援命令列的引數輸入,而後面的兩個引數最後再講。之後可以看到重要的黑體程式行——UIApplicationMain 的呼叫,通過它完成系統啟動的過程,並形成一個事件驅動。那麼是如何完成系統的啟動過程呢?可以參照Apple提供的啟動流程圖:


可以看到UIApplication首先會去檢視info.plist中記錄的一些應用的基本資訊(如下圖),其中最重要的是應用程式啟動資原始檔的名稱(nib檔案,名稱用Main nib File base name鍵指定),如何建立的是universe的應用,那麼還會包含ipad的啟動資原始檔的名稱。從下圖中我們還看到了應用圖示檔案以及支援方向感應器的方向。


從工程檔案中找到Main nib file對應的MainWindow_iPhone.xib檔案,可以看到有四個基本的專案:

1.File’s Owner 物件:實際上就是 UIApplication 的例項。

2.First Responder 物件:每個程式都會有一個第一響應者,比如滑鼠事件,鍵盤事件等,它就是對應的那個物件。比如多文件程式中,menu的響應事件一般都是連線到FirstResponder中去的,因為主介面一般都在別的nib裡面,此時的FirstResponder就是你的那個主nib的FileOwner。

3.Delegate 物件:每個程式都有一個工程名+AppDelegate類,即為該Delegate的實現。

4.Window:應用程式啟動的時候所顯示的視窗。

程式啟動時,那麼就會發送訊息給UIApplication的Delegate物件,就會呼叫AppDelegate類的applicationDidFinishLaunching: 方法。因此可以在MainWindow_iPhone.xib指定某個特定的Delegate物件,從而啟動的位置會發生改變。

而在Delegate類中的applicationDidFinishLaunching:會初始化window物件,即程式啟動時候的顯示視窗。

具體的程式碼為:

  1. <span style="font-size:14px;">- (void)applicationDidFinishLaunching:(UIApplication *)application {  
  2.     // Override point for customization after app launch
  3.     [window addSubview:UIViewControllerInstance.view];  
  4.     [window makeKeyAndVisible];  
  5. }  
  6. </span>  
[window addSubview:UIViewControllerInstance.view] 表示 在呼叫[window makeKeyAndVisible] 是顯示UIViewControllerInstance的View。

綜上所述,程式啟動的流程為:

講到這裡,如果沒有版本的更新問題,其實是可以結束了。而在XCode4.2版本之後,可能沒有了Main.xib來載入初始介面。那麼就不得不使用UIApplicationMain指定入口。前面講到了UIApplicationMain含有四個引數,這裡可以將UIApplicationMain(argc, argv, nil, nil);變成UIApplicationMain(argc, argv, nil,NSStringFromClass([AppDelegate class]));。這裡的AppDelegate為你要完成初始化介面的delegate。

除了上面的改變,版本更新還添加了故事板(storyBoard),那麼上面說的程式流程就不使用,請記住。

PS:對於iPhone app,你無法訪問iPhone整個的檔案系統,而只能訪問iPhone app的Home目錄中的檔案。在程式中可以用下面的方式來訪問檔案目錄:

方法1:

  1. NSString* documentsDirectory = [NSHomeDirectory()  
  2.         stringByAppendingPathComponent:@"Documents"];  
方法2:
  1. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);  
  2. NSString *documentsDirectory = [paths objectAtIndex:0];  
採用上面的方法你可以訪問Home目錄下的其他檔案。同時iOS還提供了一些常用的搜尋路徑常量:

常量

目錄

<Application_Home>/Library/Caches

<Application_Home>/Library/Application Support