iOS應(yīng)用的程序入口大家都知道,就是那個(gè)項(xiàng)目工程里面的main.m中的main()函數(shù)。
在xcode4.2之前main()函數(shù)是這樣的
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
而有了ARC之后,在xcode4.2之后變成了這樣
int main(int argc, char *argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([TCAppDelegate class]));
}
}
可以看到有了ARC之后NSAutoreleasePool被廢棄了,用了@autoreleasepool來代替,不管怎樣,iOS應(yīng)用的初始化都是通過這個(gè)UIApplicationMain()函數(shù)來實(shí)現(xiàn)。
UIApplicationMain()函數(shù)是初始化程序的核心,它接受4個(gè)參數(shù)。
-
argc和argv:來自于main()接受的兩個(gè)參數(shù); - 第三個(gè)參數(shù):主要類
(principal class),必須是UIApplication或其子類的名字,它代表著當(dāng)前iPhone程序本身,這個(gè)程序會(huì)去讀info.plist文件獲取配置信息,其中包括主nib文件的值,一般為MainWindow(.xib);如果該參數(shù)為nil,則默認(rèn)為@"UIApplication"; - 第四個(gè)參數(shù):代理類
(delegate class),MainWindow.xib文件中遵循UIApplicationDelegate的類的類名,因?yàn)?code>UIApplication定義了一個(gè)delegte變量,這個(gè)變量應(yīng)該遵循UIApplicationDelegate,負(fù)責(zé)控制程序的運(yùn)行,如果主nib文件沒有這個(gè)類,你應(yīng)該自定義一個(gè)這樣的類,并將第四個(gè)參數(shù)改為這個(gè)類的類名,否則這個(gè)程序不知道如何進(jìn)行運(yùn)作,因?yàn)榍叭齻€(gè)參數(shù)代表應(yīng)用程序本身,它除了把應(yīng)用的事件循環(huán)啟動(dòng)起來,并讀取info.plist里的配置信息,不做其它任何事情。如果該參數(shù)為nil,則程序假設(shè)程序的代理來自Main nib文件。
iOS應(yīng)用生命周期
UIApplicationMain函數(shù)主要負(fù)責(zé)三件事情:
- 從給定的類名初始化應(yīng)用程序?qū)ο?/strong>,也就是初始化UIApplication或者子類對(duì)象的一個(gè)實(shí)例,如果你在這里給定的是nil,那么系統(tǒng)會(huì)默認(rèn)UIApplication類,也就主要是這個(gè)類來控制以及協(xié)調(diào)應(yīng)用程序的運(yùn)行。在后續(xù)的工作中,你可以用靜態(tài)方法sharedApplication 來獲取應(yīng)用程序的句柄。
- 從給定的應(yīng)用程序委托類,初始化一個(gè)應(yīng)用程序委托。并把該委托設(shè)置為應(yīng)用程序的委托,這里就有如果傳入?yún)?shù)為nil,會(huì)調(diào)用函數(shù)訪問 Info.plist文件來尋找主nib文件,獲取應(yīng)用程序委托。
-
啟動(dòng)主事件循環(huán),并開始接收事件。
上面是UIApplicationMain函數(shù)的工作,接下來一個(gè)問題是應(yīng)用程序視圖的顯示、消息的控制怎么辦?下面就是UIApplication(或者子類)對(duì)象的職責(zé),這個(gè)對(duì)象主要做下面幾件事:
- 負(fù)責(zé)處理到來的用戶事件,并分發(fā)事件消息到應(yīng)該處理該消息的目標(biāo)對(duì)象(sender, action)。
- 管理以及控制視圖,包括呈現(xiàn)、控制行為、當(dāng)前顯示視圖等。
- 該對(duì)象有一個(gè)應(yīng)用程序委托對(duì)象,當(dāng)一些生命周期內(nèi)重要事件(可以包括系統(tǒng)事件或者生命周期控制事件)發(fā)生時(shí),應(yīng)用程序通知該對(duì)象。例如,應(yīng)用程序啟動(dòng)、內(nèi)存不夠了或者應(yīng)用程序結(jié)束等,讓這些事件發(fā)生時(shí),應(yīng)用程序委托去響應(yīng)。
通過上面的分析,可以知道UIApplication對(duì)開發(fā)者來說,是一個(gè)黑箱,它也可以是。因?yàn)樗械牟僮鳎伎梢杂伤奈衼韼臀覀兺瓿?,它只需要在后面維護(hù)一些不可更改的東西,如事件消息分發(fā)和傳遞、給委托發(fā)送事件處理請(qǐng)求等等,如,應(yīng)用程序加載處理完畢,它會(huì)發(fā)送消息給委托,然后委托可以在applicationDidFinishLanching委托函數(shù)中去實(shí)現(xiàn)開發(fā)者想要的動(dòng)作。利用XCODE在創(chuàng)建應(yīng)用程序時(shí),會(huì)默認(rèn)實(shí)現(xiàn)一個(gè)應(yīng)用程序委托類。而對(duì)于加載的視圖,則有視圖相關(guān)的委托類來處理視圖加載過程的生命事件。下面說明委托主要可以辦哪些事情:
控制應(yīng)用程序的行為
-(void)applicationDidFinishLaunching:(UIApplication *)application
應(yīng)用程序啟動(dòng)完畢。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
當(dāng)由于其它方法打開應(yīng)用程序(如URL指定或者連接),通知委托啟動(dòng)完畢
- (void)applicationWillTerminate:(UIApplication *)application
通知委托,應(yīng)用程序?qū)⒃陉P(guān)閉退出,請(qǐng)做一些清理工作。
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
通知委托,應(yīng)用程序收到了為來自系統(tǒng)的內(nèi)存不足警告。
-(void)applicationSignificantTimeChange:(UIApplication *)application
通知委托系統(tǒng)時(shí)間發(fā)生改變(主要是指時(shí)間屬性,而不是具體的時(shí)間值)
打開URL
-(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
打開指定的URL
控制狀態(tài)欄方位變化
- (void)application:(UIApplication *)application willChangeStatusBarOrientation:(UIInterfaceOrientation)newStatusBarOrientation duration:(NSTimeInterval)duration
設(shè)備方向?qū)⒁l(fā)生改變
- (void)application:(UIApplication *)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation
設(shè)備方向發(fā)生改變
活動(dòng)狀態(tài)改變
-(void)applicationWillResignActive:(UIApplication *)application
通知委托應(yīng)用程序?qū)⑦M(jìn)入非活動(dòng)狀態(tài),在此期間,應(yīng)用程序不接收消息或事件。
-(void)applicationDidBecomeActive:(UIApplication *)application
通知委托應(yīng)用程序進(jìn)入活動(dòng)狀態(tài),請(qǐng)恢復(fù)數(shù)據(jù)
各種狀態(tài)的委托對(duì)應(yīng)的通知
UIKIT_EXTERN NSNotificationName const UIApplicationDidEnterBackgroundNotification NS_AVAILABLE_IOS(4_0);
UIKIT_EXTERN NSNotificationName const UIApplicationWillEnterForegroundNotification NS_AVAILABLE_IOS(4_0);
UIKIT_EXTERN NSNotificationName const UIApplicationDidFinishLaunchingNotification;
UIKIT_EXTERN NSNotificationName const UIApplicationDidBecomeActiveNotification;
UIKIT_EXTERN NSNotificationName const UIApplicationWillResignActiveNotification;
UIKIT_EXTERN NSNotificationName const UIApplicationDidReceiveMemoryWarningNotification;
UIKIT_EXTERN NSNotificationName const UIApplicationWillTerminateNotification;
UIKIT_EXTERN NSNotificationName const UIApplicationSignificantTimeChangeNotification;
因此,在UIApplication中處理的系統(tǒng)事件時(shí),只需轉(zhuǎn)到delegate這個(gè)類去處理, 這個(gè)類對(duì)象就是應(yīng)用程序委托對(duì)象。我們可以從應(yīng)用程序的單例類對(duì)象中得到應(yīng)用程序委托的對(duì)象
UIApplicationDelegate* myDelegate = [[UIApplication sharedApplication] delegate];
UIApplication 接收到所有的系統(tǒng)事件和生命周期事件時(shí),都會(huì)把事件傳遞給UIApplicationDelegate進(jìn)行處理,對(duì)于用戶輸入事件,則傳遞給相應(yīng)的目標(biāo)對(duì)象去處理。比如我們?cè)趹?yīng)用程序被來電等消息后,可以調(diào)用應(yīng)用程序委托類的 applicationWillResignActive()方法,這個(gè)方法在用戶鎖住屏幕時(shí),也會(huì)調(diào)用,與之相適應(yīng)的是應(yīng)用程序重新被用戶打開時(shí)的委托方法。另外常用的就是內(nèi)存不足的系統(tǒng)警告,此時(shí)會(huì)調(diào)用應(yīng)用程序委托類的applicationDidReceiveMemoryWarning()方法, 然后我們就可以試著釋放一些內(nèi)存了。
(一)程序入口-UIApplicationMain詳解
