每個(gè)iPhone應(yīng)用程序都有一個(gè)UIApplication,UIApplication是iPhone應(yīng)用程序的開(kāi)始并且負(fù)責(zé)初始化并顯示UIWindow,并負(fù)責(zé)加載應(yīng)用程序的第一個(gè)UIView到UIWindow窗體中。UIApplication的另一個(gè)任務(wù)是幫助管理應(yīng)用程序的生命周期,而UIApplication通過(guò)一個(gè)名字為UIApplicationDelegate的代理類(lèi)來(lái)履行這個(gè)任務(wù)。盡管UIApplication會(huì)負(fù)責(zé)接收事件,而UIApplicationDelegate則決定應(yīng)用程序如何去響應(yīng)這些事件,UIApplicationDelegate可以處理的事件包括應(yīng)用程序的生命周期事件(比如程序啟動(dòng)和關(guān)閉)、系統(tǒng)事件(比如來(lái)電、記事項(xiàng)警告),本文會(huì)介紹如何加載應(yīng)用程序的UIView到UIWindow以及如何利用UIApplicationDelegate處理系統(tǒng)事件。
通常對(duì)于UIApplication讀者是沒(méi)必要修改它的,只需要知道UIApplication接收系統(tǒng)事件即可,而如何編寫(xiě)代碼來(lái)處理這些系統(tǒng)事件則是程序員的工作。處理系統(tǒng)事件需要編寫(xiě)一個(gè)繼承自UIApplicationDelegate接口的類(lèi),而UIApplicationDelegate接口提供生命周期函數(shù)來(lái)處理應(yīng)用程序以及應(yīng)用程序的系統(tǒng)事件,這些生命周期函數(shù)如下表所示:
UIApplicationDelegate Event-Handling Methods |
Method Signature |
1:application:didChangeStatusBarFrame: |
- (void)application:(UIApplication*)application didChangeSetStatusBarFrame:(CGRect)oldStatusBarFrame |
2:application:didChangeStatusBarOrientation: |
- (void)application:(UIApplication*)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation |
3:application:handleOpenURL: |
- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url |
4:application:willChangeStatusBarOrientation:duration: |
- (void)application:(UIApplication*)application willChangeStatusBarOrientation:
(UIInterfaceOrientation)newStatusBarOrientation |
5:application:willChangeStatusBarFrame |
- (void)application:(UIApplication)application willChangeStatusBarFrame:(CGRect)newStatusBarFrame |
6:applicationDidBecomeActive: |
- (void)applicationDidBecomeActive:(UIApplication*)application |
7:applicationDidFinishLaunching: |
- (void)applicationDidFinishLaunching:(UIApplication*)application |
8:applicationDidReceiveMemoryWarning: |
- (void)applicationDidReceiveMemoryWarning:(UIApplication*)application |
9:applicationSignificantTimeChange: |
- (void)applicationSignificantTimeChange:(UIApplication*)application |
10:applicationWillResignActive: |
- (void)applicationWillResignActive:(UIApplication*)application |
11:applicationWillTerminate: |
- (void)applicationWillTerminate:(UIApplication*)application |
表1
如果利用Xcode的模板創(chuàng)建項(xiàng)目,Xcode會(huì)為程序員創(chuàng)建繼承自UIApplicationDelegate的類(lèi),但不會(huì)自動(dòng)實(shí)現(xiàn)繼承自UIApplicationDelegate的可選的事件處理函數(shù)。如果讀者創(chuàng)建一個(gè)名為“TestUIApplication”的項(xiàng)目,Xcode會(huì)自動(dòng)創(chuàng)建TestUIApplicationAppDelegate.h和TestUIApplicationAppDelegate.m文件,文件的聲明如下:
@interface TestUIApplicationAppDelegate : NSObject 《UIApplicationDelegate》
而應(yīng)用程序的UIApplication則被定義在MainWindow.xib文件中,并且有一個(gè)作為outlet的UIApplicationDelegate引用,如下圖:
圖1
當(dāng)應(yīng)用程序接收到表1中的事件時(shí),UIApplication會(huì)調(diào)用UIApplicationDelegate中實(shí)現(xiàn)的相應(yīng)的方法。
從根本上講,委托(delegate)是iPhone中廣泛采用的一種編程方法,這種方法有很多益處:
它更為簡(jiǎn)潔的把程序的邏輯處理從UIApplication中分離了出來(lái)。
它避免了程序員直接從UIApplication派生子類(lèi),試想如果通過(guò)從UIApplication派生子類(lèi)的方法來(lái)管理應(yīng)用程序的生命周期和系統(tǒng)事件是多么痛苦的一件事情。
每個(gè)iPhone應(yīng)用程序都有一個(gè)UIApplication,UIApplication是iPhone應(yīng)用程序的開(kāi)始并且負(fù)責(zé)初始化并顯示UIWindow,并負(fù)責(zé)加載應(yīng)用程序的第一個(gè)UIView到UIWindow窗體中。UIApplication的另一個(gè)任務(wù)是幫助管理應(yīng)用程序的生命周期,而UIApplication通過(guò)一個(gè)名字為UIApplicationDelegate的代理類(lèi)來(lái)履行這個(gè)任務(wù)。盡管UIApplication會(huì)負(fù)責(zé)接收事件,而UIApplicationDelegate則決定應(yīng)用程序如何去響應(yīng)這些事件,UIApplicationDelegate可以處理的事件包括應(yīng)用程序的生命周期事件(比如程序啟動(dòng)和關(guān)閉)、系統(tǒng)事件(比如來(lái)電、記事項(xiàng)警告),本文會(huì)介紹如何加載應(yīng)用程序的UIView到UIWindow以及如何利用UIApplicationDelegate處理系統(tǒng)事件。
通常對(duì)于UIApplication讀者是沒(méi)必要修改它的,只需要知道UIApplication接收系統(tǒng)事件即可,而如何編寫(xiě)代碼來(lái)處理這些系統(tǒng)事件則是程序員的工作。處理系統(tǒng)事件需要編寫(xiě)一個(gè)繼承自UIApplicationDelegate接口的類(lèi),而UIApplicationDelegate接口提供生命周期函數(shù)來(lái)處理應(yīng)用程序以及應(yīng)用程序的系統(tǒng)事件,這些生命周期函數(shù)如下表所示:
UIApplicationDelegate Event-Handling Methods |
Method Signature |
1:application:didChangeStatusBarFrame: |
- (void)application:(UIApplication*)application didChangeSetStatusBarFrame:(CGRect)oldStatusBarFrame |
2:application:didChangeStatusBarOrientation: |
- (void)application:(UIApplication*)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation |
3:application:handleOpenURL: |
- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url |
4:application:willChangeStatusBarOrientation:duration: |
- (void)application:(UIApplication*)application willChangeStatusBarOrientation:
(UIInterfaceOrientation)newStatusBarOrientation |
5:application:willChangeStatusBarFrame |
- (void)application:(UIApplication)application willChangeStatusBarFrame:(CGRect)newStatusBarFrame |
6:applicationDidBecomeActive: |
- (void)applicationDidBecomeActive:(UIApplication*)application |
7:applicationDidFinishLaunching: |
- (void)applicationDidFinishLaunching:(UIApplication*)application |
8:applicationDidReceiveMemoryWarning: |
- (void)applicationDidReceiveMemoryWarning:(UIApplication*)application |
9:applicationSignificantTimeChange: |
- (void)applicationSignificantTimeChange:(UIApplication*)application |
10:applicationWillResignActive: |
- (void)applicationWillResignActive:(UIApplication*)application |
11:applicationWillTerminate: |
- (void)applicationWillTerminate:(UIApplication*)application |
表1
如果利用Xcode的模板創(chuàng)建項(xiàng)目,Xcode會(huì)為程序員創(chuàng)建繼承自UIApplicationDelegate的類(lèi),但不會(huì)自動(dòng)實(shí)現(xiàn)繼承自UIApplicationDelegate的可選的事件處理函數(shù)。如果讀者創(chuàng)建一個(gè)名為“TestUIApplication”的項(xiàng)目,Xcode會(huì)自動(dòng)創(chuàng)建TestUIApplicationAppDelegate.h和TestUIApplicationAppDelegate.m文件,文件的聲明如下:
@interface TestUIApplicationAppDelegate : NSObject 《UIApplicationDelegate》
而應(yīng)用程序的UIApplication則被定義在MainWindow.xib文件中,并且有一個(gè)作為outlet的UIApplicationDelegate引用,如下圖:
圖1
當(dāng)應(yīng)用程序接收到表1中的事件時(shí),UIApplication會(huì)調(diào)用UIApplicationDelegate中實(shí)現(xiàn)的相應(yīng)的方法。
從根本上講,委托(delegate)是iPhone中廣泛采用的一種編程方法,這種方法有很多益處:
它更為簡(jiǎn)潔的把程序的邏輯處理從UIApplication中分離了出來(lái)。
它避免了程序員直接從UIApplication派生子類(lèi),試想如果通過(guò)從UIApplication派生子類(lèi)的方法來(lái)管理應(yīng)用程序的生命周期和系統(tǒng)事件是多么痛苦的一件事情。
同樣,“委托模式”也是一種常用的面向?qū)ο蟮脑O(shè)計(jì)模式,這種設(shè)計(jì)模式用Java語(yǔ)言可以更好的進(jìn)行描述。
“委托模式”中一般有兩個(gè)對(duì)象參與處理同一個(gè)請(qǐng)求,所謂的請(qǐng)求在iPhone中就是應(yīng)用程序的生命周期和系統(tǒng)事件,接受請(qǐng)求的對(duì)象將請(qǐng)求委托給另一個(gè)對(duì)象來(lái)處理,同樣在iPhone中對(duì)應(yīng)的是UIApplication在接收到生命周期和系統(tǒng)事件后委托給UIApplicationDelegate來(lái)處理。同樣,委托模式也是很多其它模式的基礎(chǔ),如狀態(tài)模式、策略模式、訪問(wèn)者模式本質(zhì)上是在特殊的情況下采用了委托模式。委托模式使得可以用聚合代理繼承,正如iPhone中為了避免直接從UIApplication繼承而采用委托模式一樣。
如果用Java來(lái)模擬iPhone中委托模式的處理過(guò)程,UIApplication定義大致如下:
public class UIApplication {
public final int UP = 1;
public final int DOWN = 2;
public final int DRAG = 3;
public final int DROP = 4;
private UIApplicationDelegate Delegate;
/**
* @param args
*/
public UIApplication(UIApplicationDelegate aDelegate)
{}
public boolean HandlerSysEvents(int aEventValue)
{
switch(aEventValue)
{
case UP:
Delegate.HanlderEvents(aEventValue);
break;
case DOWN:
Delegate.HanlderEvents(aEventValue);
break;
case DRAG:
Delegate.HanlderEvents(aEventValue);
break;
case DROP:
Delegate.HanlderEvents(aEventValue);
break;
}
return false;
}
}
而委托接口UIApplicationDelegate的定義如下:
public interface UIApplicationDelegate {
public void applicationDidFinishLaunching(UIApplication application);
public boolean HanlderEvents(int aEventsValue);
}
可見(jiàn),通過(guò)傳遞UIApplicationDelegate到UIApplication中,系統(tǒng)就可以在UIApplication接收到系統(tǒng)事件時(shí)調(diào)用委托類(lèi)UIApplicationDelegate中相應(yīng)的方法來(lái)處理系統(tǒng)事件。
探究iPhone不采用繼承體系而采用委托模式來(lái)實(shí)現(xiàn)聚合的原因,其更深層次在于iPhone框架的多樣化使得繼承無(wú)法保證子類(lèi)行為的一致性,而委托模式恰恰是為了彌補(bǔ)繼承的這個(gè)缺點(diǎn)誕生的。
打開(kāi)Other Sources目錄下main.m文件,可以看到如下代碼:
#import 《UIKit/UIKit.h》
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
?。踦ool release];
return retVal;
}
每個(gè)項(xiàng)目都會(huì)有一個(gè)UIApplication對(duì)象來(lái)處理應(yīng)用程序的生命周期和系統(tǒng)事件,main()函數(shù)通過(guò)UIApplicationMain()來(lái)初始化應(yīng)用程序的UIApplication,如果讀者想對(duì)應(yīng)用程序的UIApplication進(jìn)行操作,就只能通過(guò)[UIApplication sharedApplication]來(lái)獲取到UIApplication的引用,這個(gè)方法會(huì)返回一個(gè)全局唯一的UIApplication對(duì)象給讀者。
同樣,讀者可以通過(guò)如下代碼獲取應(yīng)用程序的委托對(duì)象:
UIApplicationDelegate* myDelegate = [[UIApplication sharedApplication] delegate];
在UIApplication接收到系統(tǒng)事件和生命周期事件時(shí),會(huì)把相應(yīng)的事件傳遞給UIApplicationDelegate進(jìn)行處理,表1所列的生命周期函數(shù)大都是可選的,但為了應(yīng)用程序的健壯性程序員應(yīng)該實(shí)現(xiàn)它們。
iPhone并不是多任務(wù)的操作系統(tǒng),所以應(yīng)用程序很容易受到打擾,比如一個(gè)來(lái)電可能導(dǎo)致應(yīng)用程序失去焦點(diǎn),如果這個(gè)時(shí)候接聽(tīng)了電話,那么應(yīng)用程序會(huì)自動(dòng)終止運(yùn)行。還有很多其它類(lèi)似的事件會(huì)導(dǎo)致iPhone應(yīng)用程序失去焦點(diǎn),在應(yīng)用程序失去焦點(diǎn)前會(huì)調(diào)用委托類(lèi)的applicationWillResignActive()方法,而應(yīng)用程序再次獲取到焦點(diǎn)的時(shí)候會(huì)調(diào)用applicationDidBecomeActive()方法。比如在運(yùn)行應(yīng)用程序的時(shí)候鎖屏?xí){(diào)用委托類(lèi)的applicationWillResignActive()方法,而當(dāng)屏幕被解鎖的時(shí)候,又會(huì)調(diào)用applicationDidBecomeActive()方法。
另外一個(gè)非常重要的方法就是applicationDidReceiveMemoryWarning(),因?yàn)閕Phone設(shè)備只有有限的內(nèi)存,如果為應(yīng)用程序分配了太多內(nèi)存操作系統(tǒng)會(huì)終止應(yīng)用程序的運(yùn)行,但在終止之前操作系統(tǒng)會(huì)通過(guò)先調(diào)用委托類(lèi)的applicationDidReceiveMemoryWarning()方法警告應(yīng)用程序,在UIApplication接收到這個(gè)事件后它會(huì)傳遞給委托類(lèi)的applicationDidReceiveMemoryWarning()方法,委托類(lèi)在這個(gè)方法內(nèi)可以進(jìn)行釋放內(nèi)存的操作以防止操作系統(tǒng)強(qiáng)制終止應(yīng)用程序的運(yùn)行。