info.plist、pch和四大對象(UIApplication、UIApplicationDelegate、UIWindow、UIViewController)

1.程序配置文件info.plist,全局頭文件pch

工程的配置中Info選項裏面的內容其實是info.plist文件裏面的內容的拷貝,info.plist裏面存放了許多關於項目啓動參數的配置信息。應該注意:若想往項目中添加自定義的plist文件,應該使文件名中不包含info。info.plist修改和其餘的plist文件修改方式同樣,都是鍵值對的修改。可是要注意的是當使用Source Code方式打開該文件的時候,鍵名和用plist方式打開時不同。就xml源碼文件討論,鍵名分爲如下幾種:ios

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的行爲。
xcode

下面是一些經常使用的鍵的意義:app

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.pchide

當程序中的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介紹

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介紹,程序啓動過程

在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
ui

 

4.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.程序界面顯示出來的過程

 

當配置了啓動的時候使用main.storyboard的時候, 此時, 當程序啓動完畢後, 會自動建立UIWindow, 而後再根據main.storyboard文件建立對應的控制器, 以及控制器中的view. 而後把控制器的View添加到UIWindow上.而後咱們就看到界面了.

若是沒有爲項目配置啓動的時候使用哪一個storyboard, 那麼應用程序啓動完畢之後不會建立UIWindow對象, 以及對應的控制器等等.這時就須要本身去建立

在app代理類的FinishLaunching中

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    
// 建立一個控制器, 而後把控制器設置給UIWidnow
MKViewController *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.總結程序啓動完整過程

(有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])。
相關文章
相關標籤/搜索