Cocoa程序添加行為 使用Cocoa框架
Cocoa程序添加行為 使用Cocoa框架是本文丫介紹的內(nèi)容,當(dāng)您用Objective-C開發(fā)程序的時(shí)候,很多工作不必自己做。您要關(guān)注蘋果和其它人已經(jīng)完成的工作,關(guān)注他們已經(jīng)開發(fā)完成并封裝在Objective-C框架的類。這些框架為您提供一組獨(dú)立的類,而這些類構(gòu)成了您的程序的一部分—通常是很重要的一部分。
庫函數(shù)很少對(duì)使用它們的程序進(jìn)行限制,您可以在任何需要的時(shí)候進(jìn)行調(diào)用。另一方面,面向?qū)ο蟮膸旎?strong>框架中的方法和類的定義緊密相關(guān),如果您沒有創(chuàng)建或保留可以訪問那些定義的對(duì)象,就不能對(duì)其進(jìn)行調(diào)用。而且,在大多數(shù)程序中,對(duì)象必須至少和一個(gè)對(duì)象相連接,才能在程序網(wǎng)絡(luò)中發(fā)揮作用。一個(gè)類只負(fù)責(zé)定義一個(gè)程序組件,為了訪問類提供的服務(wù),您必須將它連接到應(yīng)用程序結(jié)構(gòu)中。
也就是說,框架類生成一些行為類似于一組庫函數(shù)的實(shí)例。您簡(jiǎn)單地創(chuàng)建一個(gè)實(shí)例,對(duì)其進(jìn)行初始化,然后或者向它發(fā)送消息使其完成某個(gè)任務(wù),或者將它插入到應(yīng)用程序中某個(gè)設(shè)計(jì)好的插槽中。舉例來說,您可以用NSFileManager類來執(zhí)行各種文件系統(tǒng)操作,比如移動(dòng)、拷貝、和刪除文件。如果您需要顯示一個(gè)警告對(duì)話框,則可以創(chuàng)建一個(gè)NSAlert類的實(shí)例,并向它發(fā)送正確的消息。
然而在一般情況下,象Cocoa這樣的環(huán)境并不僅僅是一些提供服務(wù)的、彼此獨(dú)立的類集合。它們是由一些面向?qū)ο蟮?strong>框架和面向特定問題空間并提出完整解決方案的類集合組成的。框架不是提供一些在需要時(shí)可以調(diào)用、彼此不相關(guān)的服務(wù)(象函數(shù)庫那樣),而是制訂您的代碼必須適應(yīng)的整個(gè)程序結(jié)構(gòu)—或者說程序模型。由于這個(gè)程序模型是具有一般意義的,您可以對(duì)它進(jìn)行具體化,以滿足特定的程序需要。您要做的不是設(shè)計(jì)一個(gè)調(diào)用庫函數(shù)的程序,而是將您自己的代碼插入到框架提供的設(shè)計(jì)中。
要使用框架,就必須接受框架定義和使用的程序模型,而且需要定制一些類,使面向具體應(yīng)用場(chǎng)合的程序可以和該模型相適應(yīng)。這些類相互依賴,以一個(gè)組而不是單獨(dú)類的形式出現(xiàn)。乍一看,在程序代碼中采納框架的模型需要做的工作比較有限,但事實(shí)卻相反??蚣転槟峁┝撕芏喔淖兒蛿U(kuò)展其一般行為的途徑,它只是簡(jiǎn)單地要求您接受所有Cocoa程序的基本行為方式,因?yàn)樗鼈兌蓟谕瑯拥某绦蚰P汀?/p>
框架類的類型
Cocoa框架中的類以四種方式發(fā)布它們的服務(wù):
復(fù)活方式。一些類定義了復(fù)活(off-the-shelf)對(duì)象以方便用戶使用。您可以簡(jiǎn)單地創(chuàng)建這些類的實(shí)例,并根據(jù)需要對(duì)其進(jìn)行初始化。NSControl的子類,比如NSTextField、NSButton、和NSTableView(和與之相關(guān)聯(lián)的NSCell類一起)都屬于這個(gè)范疇。雖然您也可以通過編程的方式來創(chuàng)建和初始化復(fù)活對(duì)象,但是通常還是用Interface Builder來進(jìn)行這些工作。
幕后方式。在程序運(yùn)行時(shí),Cocoa會(huì)在“幕后”為其創(chuàng)建一些框架對(duì)象。您不需要顯式分配和初始化這些對(duì)象,框架會(huì)自動(dòng)替您完成這些工作。這些類通常是私有的,但是要實(shí)現(xiàn)期望的行為。
一般類的方式??蚣苤杏幸恍┮话泐悾蛘哒f抽象類??蚣芸赡芴峁┮恍┮话泐惖木唧w子類,不經(jīng)修改就可以使用。然而您可以—在某些情況下是必須—定義您自己的子類,并重載特定的方法。NSView、NSDocument、和NSFormatter類就是這種類的例子。
委托者和通告者方式。很多框架對(duì)象將自己的動(dòng)作通知給其它對(duì)象,甚至將特定的責(zé)任委托給其它對(duì)象。傳遞這種信息的機(jī)制就是委托和通告機(jī)制。委托者對(duì)象需要公布一個(gè)被稱為非正式協(xié)議的接口,客戶對(duì)象則必須首先注冊(cè)為委托,然后實(shí)現(xiàn)該接口中的一個(gè)或多個(gè)方法。發(fā)布通告的對(duì)象要公布自己廣播的通告列表,而所有的客戶對(duì)象都可以自由監(jiān)聽其中的一個(gè)或多個(gè)公告。NSApplication、NSText、和NSWindow就是一些委托者類,而很多框架類都可以廣播通告。
某些類提供不止一種類型的服務(wù)。舉例來說,您可以將一個(gè)準(zhǔn)備好的NSWindow對(duì)象從Interface Builder的選盤中拖出,并在少量的初始化之后進(jìn)行使用。這樣,NSWindow類就為您提供了復(fù)活實(shí)例。但是一個(gè)NSWindow對(duì)象也需要向它的委托發(fā)送消息,以及向其它對(duì)象發(fā)布通告。如果需要,比如您希望有一個(gè)圓角的窗口,您甚至可以生成NSWindow的子類。
采用***兩種服務(wù)方式—即一般類方式和委托者/通告者方式—的Cocoa類為將程序的具體代碼集成到框架提供的結(jié)構(gòu)中提供***的可能性。"Cocoa類的繼承"部分就如何創(chuàng)建框架類、特別是一般類的子類進(jìn)行一般性的討論,有關(guān)委托、通告、以及程序網(wǎng)絡(luò)中的其它對(duì)象間通訊機(jī)制的信息請(qǐng)參見“和對(duì)象進(jìn)行通訊”部分。
Cocoa API的約定
在您開始使用Cocoa框架中的類、方法、和其它API的時(shí)候,需要知道一些約定,它們都是為了確保使用效率和一致性而制訂的。
返回對(duì)象的方法通常通過返回nil來表示“創(chuàng)建失敗”或者“沒有對(duì)象可以返回”。這種方法并不返回狀態(tài)碼。
返回nil的約定通常用于表示運(yùn)行時(shí)錯(cuò)誤或其它非例外的條件。Cocoa框架通過拋出例外(由最***的例外處理代碼處理)來處理諸如“數(shù)組索引越界” 或 “不能識(shí)別方法選擇器”這樣的錯(cuò)誤,如果方法簽名有要求的話,同時(shí)返回nil。
某些可能返回nil的方法可以通過***一個(gè)參數(shù)以引用的方式返回錯(cuò)誤信息。
上述的***一個(gè)參數(shù)是一個(gè)NSError對(duì)象的指針;對(duì)于執(zhí)行失敗的方法(也就是說方法返回nil),您可以通過考察返回的錯(cuò)誤對(duì)象來確定錯(cuò)誤的原因,或者將錯(cuò)誤顯示在對(duì)話框上。
以NSDocument類的一個(gè)方法為例:
- - (id)initWithType:(NSString *)typeName error:(NSError **)outError;
類似地,執(zhí)行某些系統(tǒng)操作的方法(比如文件讀寫)通常返回一個(gè)Boolean值,以指示執(zhí)行成功還是失敗。
這些方法也會(huì)將一個(gè)NSError對(duì)象指針作為***一個(gè)引用參數(shù)。以NSData類的一個(gè)方法為例:
- - (BOOL)writeToFile:(NSString *)path options:(unsigned)writeOptionsMask error:(NSError **)errorPtr;
Cocoa用空的容器對(duì)象來表示缺省值或沒有值—nil通常不是正當(dāng)?shù)膶?duì)象參數(shù)。
很多對(duì)象封裝了對(duì)象的值或集合。將這些對(duì)象作為參數(shù)的方法可以接收表示沒有值或缺省值的“空”對(duì)象(比如@"")。比如,下面的消息通過指定一個(gè)空的字符串,將一個(gè)窗口的關(guān)聯(lián)文件名設(shè)置為“沒有值”:
- [aWindow setRepresentedFilename:@""];
請(qǐng)注意:Objective-C的@“characters”構(gòu)造器用于創(chuàng)建一個(gè)包含文字字符的NSString對(duì)象,因此@““會(huì)創(chuàng)建一個(gè)不包含字符的字符串對(duì)象—或者說是一個(gè)空字符串。
Cocoa框架要求在字典鍵、通告和例外名稱、以及一些用字符串作為參數(shù)的方法上使用全局字符串常數(shù),而不是一個(gè)字符串文字。在可以進(jìn)行選擇的時(shí)候,您應(yīng)該總是選擇字符串常量,而不是字符串文字。使用字符串常量時(shí),編譯器可以幫助您進(jìn)行拼寫檢查,這樣可以避免運(yùn)行時(shí)錯(cuò)誤。Cocoa框架在類型使用上是一致的,各組API之間可以進(jìn)行較好的匹配。
舉例來說,Cocoa框架用float來表示坐標(biāo)的值,用CGFloat類型表示圖形和坐標(biāo)值,用NSPoint(由兩個(gè)CGFloat值組成)來表示坐標(biāo)系統(tǒng)中的一個(gè)位置,用NSString對(duì)象來表示字符串的值,用NSRange來表示范圍(起始點(diǎn)和偏移量),分別用NSInteger和NSUInteger來表示有符號(hào)和無符號(hào)的整數(shù)值。當(dāng)您設(shè)計(jì)自己的API時(shí),應(yīng)該盡量保持類似的一致性。相當(dāng)一部分Cocoa API約定關(guān)注于類、方法、函數(shù)、常量、和其它符號(hào)的命名。在您開始設(shè)計(jì)自己的編程接口時(shí),需要知道這些約定。一部分較為重要的命名約定如下所示:
在類名和與類相關(guān)聯(lián)的符號(hào),比如函數(shù)和typedef定義的類型上,使用前綴。使用前綴可以避免命名沖突,幫助區(qū)分不同的函數(shù)域。前綴的命名約定是使用兩個(gè)或三個(gè)唯一的大寫字母,比如ACCircle中的“AC”。在API的命名上,清楚比簡(jiǎn)潔更重要。舉例來說,removeObjectAtIndex:的功能很容易理解,但是remove:就有點(diǎn)模糊。避免模菱兩可的命名。
比如displayName就模菱兩可,因?yàn)槲覀儾磺宄墓δ苁秋@示一個(gè)名稱還是返回一個(gè)顯示名稱。在代表動(dòng)作的函數(shù)或方法名上使用動(dòng)詞。如果一個(gè)方法返回一個(gè)屬性或經(jīng)過計(jì)算的值,則直接使用屬性名作為方法名。這些方法就是所謂的“getter”存取方法。舉例來說,如果屬性是背景顏色,則getter方法應(yīng)該命名為backgroundColor。返回Boolean值的getter方法的命名有細(xì)微的區(qū)別,采用“is”或“has” 前綴—比如hasColor。
對(duì)于負(fù)責(zé)設(shè)置屬性值的方法(也就是“setter” 存取方法),則其名稱以“set”開頭,后接屬性名稱。屬性名稱的***個(gè)字母是大寫字母—比如setBackgroundColor:。請(qǐng)注意:有關(guān)如何實(shí)現(xiàn)setter和getter方法的詳細(xì)討論,請(qǐng)參見模型對(duì)象實(shí)現(xiàn)指南文檔中的“存取方法”部分。不要在API名稱上使用縮寫,如果不是眾所周知的縮寫的話(比如HTML或TIFF)。
如果需要Objective-C編程接口命名風(fēng)格的完整資料,請(qǐng)參見Cocoa編碼指南。還有一個(gè)一般性的、具有決定作用的API約定,是關(guān)于對(duì)象所有權(quán)的。簡(jiǎn)單地說,這個(gè)約定就是,如果一個(gè)客戶代碼進(jìn)行對(duì)象的創(chuàng)建(通過分配、初始化)、拷貝、和保持(通過發(fā)送retain消息),就擁有該對(duì)象的所有權(quán)。對(duì)象的所有者在不需要使用該對(duì)象時(shí),要向它發(fā)送release或者autorelease消息進(jìn)行清除。
小結(jié):Cocoa程序添加行為 使用Cocoa框架的內(nèi)容介紹完了,希望本文對(duì)你有所幫助。關(guān)于Cocoa更多的相關(guān)內(nèi)容,請(qǐng)參考編輯推薦。