info.plist、pch和四大對象(UIApplication、UIApplicationDelegate、UIWindow、UIViewController),uiviewcontroller
本文目錄
- 1.程式設定檔info.plist,全域標頭檔pch
- 2.應用程式物件UIApplication介紹
- 3.UIApplicationDelegate介紹,程式啟動過程
- 4.UIWindow對象
- 5.程式介面顯示出來的過程
- 6.總結程式啟動完整過程
-1.程式設定檔info.plist,全域標頭檔pch1.程式設定檔info.plist,全域標頭檔pch回到頂部
工程的配置中Info選項裡面的內容實際上是info.plist檔案裡面的內容的拷貝,info.plist裡面存放了許多關於項目啟動參數的配置資訊。應該注意:若想往項目中添加自訂的plist檔案,應該使檔案名稱中不包含info。info.plist修改和其他的plist檔案修改方式一樣,都是索引值對的修改。但是要注意的是當使用Source Code方式開啟該檔案的時候,鍵名和用plist方式開啟時不一樣。就xml源碼檔案討論,鍵名分為以下幾種:
Core Foundation Keys
該類的keys的特點是以CF為首碼,用以代表Core Foundation,描述了一些常用的行為項
Lanch Services Keys
載入服務項,提供了App載入所依賴的配置,描述了app啟動的方式選擇。
Cocoa Keys
Cocoa架構或Cocoa Touch架構依賴這些keys來標識更進階別的設定項目,如app的main
nib檔案,主要類。這些key描述影響著Cocoa和Cocoa Touch架構初始化和運行app的運行方式
UIKit Keys
描述IOS Apps的行為,每個IOS應用都依賴於Info.
plist的keys來與IOS系統通訊。Xcode提供了產生的plist檔案提供了所有app所需的那些比較重要的keys。 但app可能需要擴充預設的plist來描述更多的資訊,如定製app啟動後的預設旋轉方向,標識app是否支援檔案分享權限設定等等。
OS X Keys
描述了Mac Apps的行為。
下面是一些常用的鍵的意義:
1.Localiztion native development region --- CFBundleDevelopmentRegion 本地化相關,如果⽤戶所在地沒有相應的語言資源,則用這個key的value來作為預設
2.Bundle display name --- CFBundleDisplayName 設定程式安裝後顯示的名稱。應⽤程式名稱限制在10-12個字元,如果超出,將被顯示縮寫名稱。
3.Executaule dile -- CFBundleExecutable 程式安裝包的名稱
4.Bundle identidier --- CFBundleIdentidier 該束的唯一標識字串,該字串的格式類似 com.yourcompany.yourapp,如果使⽤用模擬器跑你的應用,這個欄位沒有用處,如果你需要把你的應⽤部署到裝置上,你必須⽣成一個認證,⽽而在⽣產生認證的時候,在apple的⽹網站上需要增加相應的app IDs.這⾥有一個欄位Bundle identidier,如果這個Bundle identidier是一個完整字串,那麼檔案中的這個欄位必須和後者完全相同,如果app IDs中的欄位含有萬用字元*,那麼檔案中的字串必須符合後者的描述。
5.InfoDictionary version --- CFBundleInfoDictionaryVersion Info.plist 格式的版本資訊
6.Bundle name --- CFBundleName 產品名稱
7.Bundle OS Type code -- CFBundlePackageType ⽤來標識束類型的四個字母長的代碼
8.Bundle versions string, short --- CFBundleShortVersionString ⾯向使用者市場的束的版本字串
9.Bundle creator OS Type code --- CFBundleSignature 用來標識建立者的四個字母長的代碼
10.Bundle version --- CFBundleVersion 應⽤程式版本號碼,每次部署應用程式的一個新版本時, 將會增加這個編號,在app store上用的。
11.Application require iPhone environment -- LSRequiresIPhoneOS 用於指示程式包是否只能運行在iPhone OS 系統上。Xcode自動加入這個鍵,並將它的值設定為true。您不應該改變這個鍵的值。
12.Main storybard dile base name -- UIMainStoryboardFile 這是一個字串,指定應用程式主nib檔案的名稱。
13.supported interface orientations -- UISupportedInterfaceOrientations 程式預設支援的裝置方向。
pch檔案,是prefix header file。是程式運行起來後的全域標頭檔,當添加了該檔案後,不用在其他檔案中使用#include或者是#import匯入該檔案,就可以直接使用該檔案中的各種內容,比如宏定義和常量和一些公用的類。在xcode5及之前可以直接使用pch檔案,在xcode6之後需要在Build Settings中的Apple LLVM 6.0-Language項中的Prefix Header條目中,設定pch檔案所在的目錄為$(SRCROOT)/對應的檔案夾名/PrefixHeader.pch,例如在根目錄中 可以直接設定$(SRCROOT)/PrefixHeader.pch
當程式中的NSLog較多時,會造成很大的效能問題(NSLog是一個IO操作),對於發布程式是非常不好的,如果依次找到程式中的所有NSLog並將他們刪除或者注釋,工程項是巨大的,因此可以是用在pch中設定一個條件編譯,如果是在調試狀態下NSLog為正常的代碼,如果在發布狀態下則忽略他們。
#ifdef DEBUG#define NSLog(...); NSLog(__VA_ARGS__);#else#define NSLog(...);#endif
在調試狀態下__VA_ARGS__的內容會替換為...中的內容(這是宏定義中提取方法參數中常用的方法),而在發布狀態的時候,則直接忽略了NSLog(...)
ios開發中難免會遇到一些oc與c混編的時候,當使用了pch檔案時,c檔案是不會識別上面的條件編譯和#import等指令的,這時候應該使用另外一個條件編譯來避免出現問題:
#ifdef __OBJC__ #import <UIKit/UIKit.h> #import <Foundation/Foundation.h>#endif
-2.應用程式物件UIApplication介紹2.應用程式物件UIApplication介紹回到頂部
UIApplication是一個單例類,可以做一些應用層級的操作
1.應用表徵圖右上方的訊息條數applicationIconBadgeNumber
2.連網操作時,狀態列上的等待表徵圖指標。waiting表徵圖。networkActivityIndicatorVisible
3.利用UIApplication開啟某個資源
** 開啟一個網頁:
[app openURL:[NSURL URLWithString:@"http://ios.icast.cn"]];
** 打電話
[app openURL:[NSURL URLWithString:@"tel://10086"]];
** 發簡訊
[app openURL:[NSURL URLWithString:@"sms://10086"]];
** 發郵件
[app openURL:[NSURL URLWithString:@"mailto://12345@qq.com"]];
4.通過UIApplication管理狀態列:
iOS7開始可以通過兩種方式來控制狀態列
1> 控制器- (BOOL)prefersStatusBarHidden
- (UIStatusBarStyle)preferredStatusBarStyle
2>.UIApplication
如果希望通過UIApplication來管理,步驟如下:
1> 在Info.plist檔案中增加一個配置項
* View controller-based status bar appearance = NO,
2>然後編寫如下代碼:// 還可以用方法調用的形式,這樣是可以設定動畫的
app.statusBarHidden = YES;app.statusBarStyle
-3.UIApplicationDelegate介紹,程式啟動過程3.UIApplicationDelegate介紹,程式啟動過程回到頂部
在main函數中進行的設定UIApplication對象的代理。
App容易受到幹擾。正在玩遊戲,一個電話打過來了。
* 應用程式的生命週期事件(如程式啟動和關閉)
* 系統事件(如來電)
* 記憶體警告
* … …
** 處理這些幹擾事件,就要用到AppDelegate代理對象了。
** 總結: AppDelegate的主要作用就是處理(監聽)應用程式本身的各種事件:
* 應用程式啟動完畢
* 應用程式進入後台
* 應用程式進入前台
* 記憶體警告
* 等等, 都是應用程式自身的一些事件
** 要想成為UIApplication的代理對象, 必須遵守:UIApplicationDelegate協議。
** 代理中的若干方法介紹:
1. - (BOOL)application: didFinishLaunchingWithOptions:
// app第一次啟動完畢後就會調用(當程式啟動後會顯示一張啟動圖片, 當這個圖片顯示完畢, 消失後, 就開始調用這個方法)
2. - (void)applicationDidEnterBackground:(UIApplication *)application
// 當程式進入後台時, 調用該方法。(比如:按了Home鍵, 或者一個電話打過來了, 當前程式都會進入後台。)
// 在這個方法中可以做一些儲存當前程式資料, 暫停程式的操作。
3. - (void)applicationWillEnterForeground:(UIApplication *)application
// 當程式再次進入前台的時候調用。
4. - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
// 當發生記憶體警告時觸發該事件。
程式啟動後:
didFinishLaunchingWithOptions-->applicationDidBecomeActive
按home鍵使程式進入後台:applicationWillResignActive--->applicationDidEnterBackground
讓程式會到主介面:applicationWillEnterForeground--->applicationDidBecomeActive
在主介面時讓程式退出:applicationDidEnterBackground--->applicationWillTerminate
在後台時退出:applicationWillTerminate
-4.UIWindow4.UIWindow對象回到頂部
** UIWindow是一種特殊的UIView, UIWindow也是繼承自UIView。
** 通常一個app只會有一個UIWindow對象。
** iOS程式啟動完畢後,建立的第一個視圖控制項就是UIWindow,接著建立控制器的view,最後將控制器的view添加到UIWindow上,於是控制器的view就顯示在螢幕上了
** 一個iOS程式之所以能顯示到螢幕上,完全是因為它有UIWindow
** 在文檔中找: Cocoa Touch Layer -> UIKit -> Guides -> View Controller Programming Guide for iOS -> View Controller Basics -> 關於UIWindow與控制器View的關係圖片。
** 建立過程UIWindow -> UIViewController -> UIView -> 把UIView加到UIWindow對象中。
-5.程式介面顯示出來的過程5.程式介面顯示出來的過程回到頂部
當配置了啟動的時候使用main.storyboard的時候, 此時, 當程式啟動完畢後, 會自動建立UIWindow, 然後再根據main.storyboard檔案建立對應的控制器, 以及控制器中的view. 然後把控制器的View添加到UIWindow上.然後我們就看到介面了.
如果沒有為項目配置啟動的時候使用哪個storyboard, 那麼應用程式啟動完畢以後不會建立UIWindow對象, 以及對應的控制器等等.這時就需要自己去建立
在app代理類的FinishLaunching中
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; // 建立一個控制器, 然後把控制器設定給UIWidnowMKViewController *mkViewCotroller = [[MKViewController alloc] init];// 設定hmVc為self.window的根控制器self.window.rootViewController = mkViewCotroller;// 把這個(self.window)設定為主視窗, 並且顯示出來[self.window makeKeyAndVisible];
需要注意的是:
不要直接把控制項添加到UIWindow上, 而是要現建立控制器, 然後向控制器所管理的view中添加子控制項, 然後把控制器設定給UIWindow.
原因:
1> UIWindow一直會存在, 直到應用程式退出.所有加到UIWindow中的子控制項也就一直會被UIWindow強引用.
2> 如果直接把子控制項加到UIWindow中, 那麼所有子控制項的事件都需要讓應用程式代理程式來監聽.
實際是應該讓對應的控制器來監聽這些事件.
3> 當旋轉螢幕的時候, UIWindow監聽到了這個旋轉事件, 然後把它傳遞給控制器, 控制器再讓對應的子控制項做旋轉.如果要是直接向UIWindow中添加子控制項, 那麼就沒有控制器, 子控制項無法監聽旋轉事件.
-6.總結程式啟動完整過程6.總結程式啟動完整過程回到頂部
(有storyboard和沒有storyboard的分別總結)
沒有storyboard檔案1. 調用main函數。
2. 調用UIApplicationMain函數。
3. 建立UIApplication對象 、 AppDelegate對象
4. 設定UIApplicatio對象的代理是AppDelegate對象。
5. AppDelegate對象開始監聽"系統事件(應用程式的事件)",進入"事件迴圈"。
6. 程式啟動完畢後調用 application: didFinishLaunchingWithOptions:方法。
----7. 在application: didFinishLaunchingWithOptions:方法中建立:
* UIWindow
* 控制器
* 設定UIWindow的根控制器是剛才建立的控制器
* 顯示UIWindow
有storyboard檔案回到頂部1. 調用main函數。
2. 調用UIApplicationMain函數。
3. 建立UIApplication對象 、 AppDelegate對象
4. 設定UIApplicatio對象的代理是AppDelegate對象。
5. AppDelegate對象開始監聽"系統事件(應用程式的事件)",進入"事件迴圈"
6. 程式啟動完畢後調用 application: didFinishLaunchingWithOptions:方法。
----7. 在application: didFinishLaunchingWithOptions:方法中建立:
* 系統自動建立UIWindow對象。
* 根據Info.plist檔案配置(Main Interface),找到需要載入的storyboard檔案(Main.storyboard)
* 找到Main.storyboard中的Is Initial View Controller 對應的控制器類, 建立該控制器對象。
* 根據storyboard中的配置, 建立控制器對應的view。
* 設定UIWindow的根控制器(rootViewController)為剛才建立的控制器。
* 顯示UIWindow([self.window makeKeyAndVisible])。