成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Cocoa 編碼指南 框架開發(fā)者使用技巧和技術(shù)

移動開發(fā) iOS
在面向?qū)ο筌浖斓脑O(shè)計(jì)過程中,開發(fā)人員經(jīng)常忽視對類、方法、函數(shù)、常量以及其他編程接元素的命名。本節(jié)介紹的是框架開發(fā)者使用技巧和技術(shù)。

Cocoa 編碼指南 框架開發(fā)者使用技巧和技術(shù)是本文要介紹的內(nèi)容,相對于其他的開發(fā)者而言,框架開發(fā)者要更加注意編寫代碼的方式。因?yàn)樵S多客戶應(yīng)用程序可能鏈接到框架,而這樣寬泛地暴露接口,就導(dǎo)致框架的任何缺點(diǎn)都可能通過系統(tǒng)放大。下面的條款討論一些框架編程技術(shù),框架開發(fā)者可以利用它們來確保框架的高效性和完整性。

請注意:此處所討論的一些技術(shù)并不局限于框架開發(fā)。將之用于應(yīng)用程序開發(fā)同樣卓有成效。

初始化

下述意見和建議涵蓋框架初始化方面的內(nèi)容。

類的初始化

initialize類方法中的代碼只執(zhí)行一次,它是類里面***個(gè)被調(diào)用的方法。我們通常利用該方法來設(shè)置類的版本號(請參考“版本化和兼容性”一節(jié))。

對于繼承鏈中的每一個(gè)類,不論其是否實(shí)現(xiàn)initialize方法,運(yùn)行時(shí)都會向它發(fā)送initialize消息。這可能導(dǎo)致一個(gè)類的initialize方法被多次調(diào)用(舉個(gè)例子,如果子類沒有實(shí)現(xiàn)initialize方法,則其父類的方法將被調(diào)用兩次)。但通常您希望始化代碼僅執(zhí)行一次,為確保如此,您可以執(zhí)行如下檢查:

  1. if (self == [NSFoo class]) {   
  2.     // the initializing code   
  3. }  

您不應(yīng)該顯式地調(diào)用initialize方法。如果需要觸發(fā)初始化行為,則請調(diào)用一些無害的方法,例如:

  1. [NSImage self];  

指定初始化函數(shù)

指定初始化函數(shù)是類的一個(gè)init方法,它調(diào)用超類的某個(gè)init方法(其他的初始化函數(shù)調(diào)用類自己定義的init方法)。每個(gè)公共類都應(yīng)包含一個(gè)或多個(gè)指定初始化函數(shù)。舉些例子,NSView的initWithFrame:方法以及NSResponder的init方法都是指定初始化函數(shù)。在某些情況下,類的init方法并不想被重載,比如NSString和其他面向類簇的抽象類,因而其子類應(yīng)該實(shí)現(xiàn)自己的初始化方法。

您應(yīng)該明確標(biāo)示出指定初始化函數(shù),因?yàn)樵撔畔τ谙敫鶕?jù)您的類來派生子類的開發(fā)者有重要的意義。一個(gè)子類可以只重載指定初始化函數(shù),這對其他所有初始化函數(shù)沒有影響,它們?nèi)詫雌湓仍O(shè)計(jì)的行為工作。

在實(shí)現(xiàn)一個(gè)框架類時(shí),您經(jīng)常需要為其實(shí)現(xiàn)諸如initWithCoder:以及encodeWithCoder:這樣的歸檔方法。請注意,對象解檔時(shí)未發(fā)生的事情不要放在初始化代碼路徑里執(zhí)行。對于實(shí)現(xiàn)歸檔功能的類,我們有一個(gè)比較好的方法可以做到這一點(diǎn),那就是在類的指定初始化方法以及initWithCoder: 方法(該方法也是個(gè)指定初始化函數(shù))中調(diào)用一個(gè)公共的例程。

初始化過程中的錯(cuò)誤檢測

為確保能夠恰當(dāng)?shù)貦z測并傳播錯(cuò)誤,一個(gè)設(shè)計(jì)良好的初始化方法應(yīng)完成如下步驟:

調(diào)用super的init方法對self重新賦值。

檢測指定初始化方法的返回值是否為nil。返回值為nil表明超類的初始化過程出現(xiàn)錯(cuò)誤。

如果當(dāng)前類在初始化的過程中出現(xiàn)錯(cuò)誤,則請釋放對象并且返回nil值。

列表1 描述的方法可以完成上述步驟。

列表1  初始化過程中的錯(cuò)誤檢測

  1. (id)init {   
  2.     if ((self = [super init]) != nil) {   // call a designated initializer here   
  3.         // initialize object  ...   
  4.         if (someError) {   
  5.             [self release]; // [self dealloc] or [super dealloc] might be   
  6.             self = nil;     // better if object is malformed   
  7.         }   
  8.     }   
  9.     return self;   
  10. }  

版本化和兼容性

在向框架添加新類或新方法時(shí),您通常沒必要為每個(gè)新功能群指定新的版本號。因?yàn)橐话闱闆r下,開發(fā)者會執(zhí)行(或者說,應(yīng)該執(zhí)行)諸如respondsToSelector:這種Objective-C的運(yùn)行時(shí)檢測來判斷給定的系統(tǒng)是否存在某種功能。開發(fā)者比較喜歡使用這種方式來檢測新功能,同時(shí)它也是最動態(tài)的方式。

不論如何,您可以使用數(shù)種技術(shù)以確保新版本的框架能被正確標(biāo)志并盡可能地兼容早期版本。

框架的版本

如果已存在的新功能或者錯(cuò)誤改正不容易通過運(yùn)行時(shí)進(jìn)行檢測,則您應(yīng)該為開發(fā)者提供檢測這些變更的辦法。有一種辦法是把確切的框架版本號保存起來,然后讓該號碼對開發(fā)者可見:

把變更歸檔在一個(gè)版本號下面(例如,歸檔在發(fā)布記錄中)。

設(shè)置框架的當(dāng)前版本號并且提供某種方法使之全局可見。您可以把版本號保存在框架的信息屬性列表(Info.plist),這樣就可以從該列表獲取版本號。

基于鍵的歸檔

如果框架對象需要被寫入到nib文件,則它們必須能夠自我歸擋 。另外,如果文檔使用歸擋機(jī)制來保存文檔數(shù)據(jù),則您也要對它們做歸擋。在歸擋時(shí),您可以使用“老風(fēng)格”(利用initWithCoder:和encodeWithCoder:這樣的方法)。但是,為了更好地兼容過去、現(xiàn)在、以及未來的框架版本,您應(yīng)該基于健進(jìn)行歸檔。

基于鍵進(jìn)行歸檔,對象就可以使用鍵來讀取或?qū)懭氡粴w擋值。相對以往的歸擋機(jī)制,該方法可以在前向和后向兼容性上提供更多的靈活性。因?yàn)槔蠚w檔機(jī)制要求代碼和讀取或?qū)懭氲闹稻S持相同的順序,而且它也沒有什么好辦法來改變已寫到檔案的數(shù)據(jù)。如果您需要了解更多基于鍵的歸檔機(jī)制,請參考 Cocoa歸檔和序列化編程指南 (Archives and Serializations Programming Guide for Cocoa)一文。

對于正在編寫的新的類,請為其使用基于鍵的歸檔機(jī)制。如果之前已發(fā)布的類使用了老歸檔機(jī)制,您也無需再采取任何措施。如果對象實(shí)現(xiàn)了Mac OS X 10.2版本之前的歸檔機(jī)制,則它必須能從檔案中讀取內(nèi)容并能其內(nèi)容寫入到檔案。但如果您在Mac OS X v10.2及之后的平臺上為該對象添加新屬性,則您不必,實(shí)際上是不應(yīng)該,將這些屬性保存到老檔案中(這樣做可能會使老檔案在更早的系統(tǒng)中變得不可讀取),這種情況下,新屬性應(yīng)使用鍵值歸檔機(jī)制。

請注意下列和基于鍵歸檔相關(guān)的事實(shí):

如果檔案中的某個(gè)鍵丟失,則在獲取這個(gè)鍵對應(yīng)值的時(shí)候,依據(jù)所要求的類型,其返回值可能是nil、 NULL、NO、0、或者0。通過對該返回值進(jìn)行測試,您可以減少寫到檔案中的數(shù)據(jù)。同時(shí),還可以檢測某個(gè)鍵是否已被寫入到檔案中。

如果使用舊式歸檔,則initWithCoder:的實(shí)現(xiàn)需要獨(dú)自挑起兼容性的重?fù)?dān)。但如果使用鍵值歸檔,則歸檔方法和解檔方法都可以采取一些措施以保證兼容性。舉個(gè)例子,一個(gè)新版本的類的歸檔方法可能使用鍵來寫入一個(gè)新值,而依舊把早期的字段寫入到檔案中,這樣類的舊版本仍然可以理解該對象。與此同時(shí),我們還可以在解檔方法中使用某種合理的方式以處理數(shù)值缺失的情況,從而為將來的版本保留一些靈活性。

在命名框架類的檔案鍵時(shí),我們提倡使用和框架其他API元素一樣的前綴,前綴后面再使用實(shí)例變量名稱。您只要確保它的名稱不會和任意的子類或者超類名稱發(fā)生沖突即可。

如果您使用一個(gè)工具函數(shù)向檔案中寫入一個(gè)基本數(shù)據(jù)類型(換句話說,就是一個(gè)非對象的值),則請務(wù)必為該數(shù)值使用一個(gè)唯一鍵。舉個(gè)例子,如果您有一個(gè)對矩形歸檔的“archiveRect” 例程,則您應(yīng)該為該函數(shù)傳入一個(gè)鍵作為參數(shù)。您可以直接把它作為檔案鍵;或者,如果這個(gè)例程向檔案寫入多個(gè)值(例如,寫入四個(gè)浮點(diǎn)數(shù)值),則它應(yīng)該把每個(gè)數(shù)值自身獨(dú)有的位添加到所提供的鍵上面。

位字段對于編譯器和比特序有依賴關(guān)系,按照位字段現(xiàn)有的格式進(jìn)行歸檔可能會有危險(xiǎn)。只有當(dāng)有多個(gè)位元需要被寫入檔案多次時(shí),我們才會對位字段進(jìn)行歸檔,這主要是為了提高性能。請參看 “位字段”一節(jié) 以獲取相關(guān)的建議。

對象的尺寸和保留字段

每個(gè)Objective-C的對象都有一個(gè)尺寸,它由對象自身實(shí)例變量加上對象所有超類具有的實(shí)例變量得到的總尺寸決定。如果改變了一個(gè)類的尺寸,則其擁有實(shí)例變量的子類必須重新編譯。為了保持二進(jìn)制兼容性,通常情況下,我們不能通過向類添加新的實(shí)例變量或者去除類里面不必要的實(shí)例變量來改變對象的尺寸。

因此,對于新的類,為其留下幾個(gè)額外的”保留“字段以便于將來擴(kuò)展是個(gè)不錯(cuò)的想法。如果一個(gè)類只會有少數(shù)的幾個(gè)實(shí)例,這個(gè)想法顯然不成問題。但如果這個(gè)類會被實(shí)例化數(shù)千次,則您可能需要讓保留的單個(gè)變量的尺寸小一些(也就是說,任意對象都占用四個(gè)字節(jié))。

對于較早的類的對象,如果它們的空間已經(jīng)用完(并且假定實(shí)例變量沒有被導(dǎo)出成為公共變量),則您可以移動實(shí)例變量,或者把它們捆綁在一起,使之成為一個(gè)更小的字段。通過對實(shí)例變量進(jìn)行重新排布,您就有可能添加新的數(shù)據(jù)而不會導(dǎo)致對象的總尺寸發(fā)生改變。或者您可以把一個(gè)剩余的保留槽作為指針,使它可以指向一塊額外的內(nèi)存,然后您在對象初始化的時(shí)候分配這塊內(nèi)存(并且在對象釋放的時(shí)候銷毀它)。又或者您可以把額外的數(shù)據(jù)放入到一張外部的哈希表(例如放入NSDictionary);這種方法對于那些很少創(chuàng)建使用的實(shí)例變量具有很好的效果。

異常和錯(cuò)誤

大多數(shù)Cocoa框架的方法不會強(qiáng)制要求開發(fā)者捕捉處理異常,因?yàn)槌绦蛘?zhí)行時(shí)不會產(chǎn)生異常,而且我們通常也不使用異常來表示可預(yù)期的運(yùn)行時(shí)錯(cuò)誤或用戶錯(cuò)誤。下面這些例子屬于可預(yù)期的運(yùn)行時(shí)錯(cuò)誤或者用戶錯(cuò)誤:

文件找不到

用戶不存在

試圖打開應(yīng)用程序中一個(gè)錯(cuò)誤類型的文檔

把字符串轉(zhuǎn)化為特定編碼時(shí)出現(xiàn)錯(cuò)誤

但是不管怎么樣, Cocoa確實(shí)會引發(fā)異常以指示下面這些編程錯(cuò)誤或者邏輯錯(cuò)誤:

數(shù)組索引越界

試圖改變一個(gè)不可改變的對象

錯(cuò)誤參數(shù)類型

我們認(rèn)為應(yīng)用程序推向市場之前,開發(fā)者會對其進(jìn)行測試,發(fā)現(xiàn)并解決這些類型的錯(cuò)誤。因此,應(yīng)用程序不需要在運(yùn)行時(shí)處理上述異常。如果出現(xiàn)一個(gè)異常發(fā)生但應(yīng)用程序沒有捕捉,則最頂層的缺省處理器通常會捕捉并且報(bào)告該異常,然后程序?qū)⒗^續(xù)執(zhí)行。開發(fā)者可以選擇替換掉這個(gè)缺省的異常處理器,新的處理器可以更詳細(xì)地描述什么地方發(fā)生了錯(cuò)誤,并且還能夠讓用戶選擇是否保存數(shù)據(jù)并且推出應(yīng)用程序。

錯(cuò)誤是Cocoa框架不同于其他軟件庫的又一個(gè)地方。Cocoa的方法通常不返回錯(cuò)誤碼。某些情況下,一個(gè)錯(cuò)誤具有一個(gè)合理或者可能的原因,方法通過對一個(gè)布爾值或者對象返回值(nil/non-nil)進(jìn)行簡單測試以判斷該情況;但是返回NO或者nil值的原因則被記錄在文檔中。另外,您不應(yīng)該使用錯(cuò)誤碼來指示需要在運(yùn)行時(shí)處理的編程錯(cuò)誤,相反您應(yīng)該引發(fā)一個(gè)異常,或者在某些情況下,您也可以只記錄下該錯(cuò)誤而不引發(fā)異常。

舉個(gè)例子,NSDictionary的objectForKey:方法會返回所找到的對象,如果對象找不到,則它會返回nil值。NSArray的objectAtIndex:法不可能返回nil值(除非我們把通用的編程語言約定重載成向nil對象發(fā)送消息都會返回nil值),因?yàn)镹SArray對象不能保存nil值,并且所有的越界訪問都被定義成編程錯(cuò)誤,這種錯(cuò)誤引發(fā)異常而并不返回nil對象。如果對象不能使用用戶提供的參數(shù)進(jìn)行初始化,許多init方法都會返回nil值

在少數(shù)情況下,一個(gè)方法需要多個(gè)不同的錯(cuò)誤碼是合理的。這時(shí),該方法需要將錯(cuò)誤碼指定到一個(gè)傳引用參數(shù),然后您可以利用該參數(shù)返回一個(gè)錯(cuò)誤碼,也可以返回一個(gè)本地化的錯(cuò)誤字符串,或者一些其他的可以描述錯(cuò)誤的信息。舉個(gè)例子,您可以把錯(cuò)誤轉(zhuǎn)換成NSError對象返回(請參看Foundation框架的NSError.h頭文件以獲取更多的細(xì)節(jié))。而除了這個(gè)NSError對象,方法還能直接返回相對簡單的BOOL值或者nil值。另外要注意,這種方法的所有傳引用參數(shù)都是可選的。因此,如果發(fā)送者不想了解錯(cuò)誤原因,它們可以傳一個(gè)NULL 值給錯(cuò)誤碼參數(shù)。

重要: NSError類在Mac OS X v10.3之后的版本對外公開。

框架數(shù)據(jù)

框架數(shù)據(jù)的處理方式可能會對性能、跨平臺兼容性、以及其他某些方面產(chǎn)生影響。本節(jié)討論一些和框架數(shù)據(jù)相關(guān)的技術(shù)。

常量數(shù)據(jù)

出于性能的原因,您應(yīng)盡可能多地把框架數(shù)據(jù)標(biāo)志為常量,因?yàn)檫@樣可以減小Mach-O二進(jìn)制文件的__DATA 段的尺寸。沒有const標(biāo)記的全局或靜態(tài)的數(shù)據(jù)最終會存放在__DATA段的__DATA節(jié)。對于每一個(gè)使用該框架的應(yīng)用程序?qū)嵗@種類型的數(shù)據(jù)都會占用內(nèi)存。盡管多出500字節(jié)(舉個(gè)例子)好像沒那么糟糕,但是這有可能導(dǎo)致應(yīng)用程序所需的內(nèi)存頁面的數(shù)量增多—即每個(gè)應(yīng)用程序都需要額外的四千字節(jié)的內(nèi)存。

您應(yīng)該為所有不變的數(shù)據(jù)添加const標(biāo)記。具有const標(biāo)記的數(shù)據(jù)塊,如果其中沒有char *類型的指針,則該數(shù)據(jù)會被存放在__TEXT段中(這會使數(shù)據(jù)成為真正的常量);否則數(shù)據(jù)就會被存放在__DATA段中,但是這些數(shù)據(jù)不可以被寫入(除非預(yù)綁定未完成,如果預(yù)邦定已經(jīng)完成,則只能在加載的時(shí)候,通過移動二進(jìn)制文件的方式來寫入)。

您應(yīng)該初始化靜態(tài)變量,這樣可以確保該變量被合并到__DATA段的__data節(jié)中而非__bss節(jié)。如果沒有明顯的值用于初始化靜態(tài)變量,則請使用0、NULL、0.0、或者任何恰當(dāng)?shù)闹怠?/p>

位字段

如果使用有符號的值來表示位字段,而代碼又假定這個(gè)位字段是布爾值,則可能會導(dǎo)致未定義的行為。只有一個(gè)位的位字段尤為如此。因?yàn)樵谶@種情況下,這個(gè)位字段只能存儲0和 -1(取決于編譯器的實(shí)現(xiàn)),把它和1做比較,其結(jié)果總是不相等。因此,只有一個(gè)位的位字段應(yīng)該是無符號的。舉個(gè)例子,如果您在代碼中遇到如下情況:

  1. BOOL isAttachment:1;   
  2. int startTracking:1;  

您應(yīng)該把上述代碼中的類型改為unsigned int

和位字段相關(guān)的另一個(gè)問題是歸檔。通常情況下,您不應(yīng)該按照當(dāng)前格式將其寫入到磁盤或者檔案中,因?yàn)楫?dāng)我們在另外的架構(gòu)或者編譯器中讀取這些字段時(shí),它們的格式可能發(fā)生變化。

內(nèi)存分配

框架代碼中,如果可以的話,***是完全避免分配內(nèi)存。如果出于某種原因,您需要一塊臨時(shí)的緩沖區(qū),則通常情況下,使用棧比分配緩沖區(qū)更好。但是,棧的大小有限(棧總的大小通常為512千字節(jié)), 因此是否使用棧取決于函數(shù)和您所需要的緩沖區(qū)的大小。通常情況下,如果您需要的緩沖區(qū)的大小不超過1000(或者是MAXPATHLE定義的值)字節(jié),使用棧是合適的。

一個(gè)比較精細(xì)的方法是在開始的時(shí)候使用棧,但是如果所需要的內(nèi)存的大小超過了棧緩沖區(qū)的大小,則切換到malloc內(nèi)存分配方式。列表 2展示的代碼片段就是這么做的。

列表 2  使用棧內(nèi)存和通過malloc分配的緩沖區(qū)

  1. #define STACKBUFSIZE (1000 / sizeof(YourElementType))   
  2.  YourElementType stackBuffer[STACKBUFSIZE];   
  3.  YourElementType *buf = stackBuffer;   
  4.  int capacity = STACKBUFSIZE;  // In terms of YourElementType   
  5.  int numElements = 0;  // In terms of YourElementType   
  6.     
  7. while (1) {   
  8.     if (numElements > capacity) {  // Need more room   
  9.         int newCapacity = capacity * 2;  // Or whatever your growth algorithm is   
  10.         if (buf == stackBuffer) {  // Previously using stack; switch to allocated memory   
  11.             buf = malloc(newCapacity * sizeof(YourElementType));   
  12.             memmove(buf, stackBuffer, capacity * sizeof(YourElementType));   
  13.         } else {  // Was already using malloc; simply realloc   
  14.             buf = realloc(buf, newCapacity * sizeof(YourElementType));   
  15.         }   
  16.         capacity = newCapacity;   
  17.     }   
  18.     // ... use buf; increment numElements ...   
  19.   }   
  20.   // ...   
  21.   if (buf != stackBuffer) free(buf);  

語言問題

下面的條款討論和Objective-C語言相關(guān)的問題,包括協(xié)議、對象比較、以及向?qū)ο蟀l(fā)送autorelease消息的時(shí)機(jī)。

向nil對象發(fā)送消息

在Objective-C中,只要消息的返回值是對象、任意的指針類型、或是其尺寸小于等于sizeof(void*)的整數(shù)型標(biāo)量,我們就可以將其發(fā)送給nil對象,該消息將返回nil值。這個(gè)特性一種很有價(jià)值的編程資產(chǎn),但是有一個(gè)問題需要注意。如果發(fā)送給nil對象的消息的返回值非上述類型(例如,消息返回任意的struct類型,或者浮點(diǎn)類型,或者任意的向量類型),則消息的返回值未定義。通常情況下,如果消息的返回值不是一個(gè)對象,則不要依賴這種行為,因?yàn)槟鞘呛茉愀獾淖龇āT赑ower PC系統(tǒng)中,向nil對象發(fā)送上述類型的消息不會有問題,但對于其他架構(gòu)來說,這種行為行不通。

對象比較

通用的對象比較方法isEqual:和與對象類型關(guān)聯(lián)在一起的比較方法(諸如isEqualToString:)有一個(gè)重要的不同。isEqual:方法允許任何對象作為參數(shù),如果用于比較的對象屬于不同的類,則該方法將返回NO值。而諸如isEqualToString:以及isEqualToArray:這樣的方法通常都假定參數(shù)是某種特定的類型(和接收者一樣的類型)。因此,這種函數(shù)不會執(zhí)行類型檢查,這使得它們運(yùn)行速度比普通的對象比較方法快,但是安全性則不如之。對于那些從外部源獲取的值,例如從應(yīng)用程序的的信息屬性表(Info.plist)或者應(yīng)用程序的偏好設(shè)置獲取的值,在對其進(jìn)行比較時(shí),我們傾向于使用isEqual:方法,因?yàn)檫@種方法更安全;但如果我們已知道要進(jìn)行比較的值的類型,則應(yīng)使用isEqualToString:方法。

關(guān)于isEqual:方法,還有一點(diǎn)就是它和hash方法的聯(lián)系。存放在基于散列的Cocoa集合類里的對象(例如存放在NSDictionary或者NSSet中的對象)有一個(gè)基本的不變式,即如果[A isEqual:B] == YES,則[A hash] == [B hash]也成立。因此,如果您重寫了類的isEqual:方法,則您也應(yīng)重寫hash方法以保持不變式成立。缺省情況下,isEqual:方法判斷對象地址指針是否相等,而hash方法則返回一個(gè)基于對象地址產(chǎn)生的hash數(shù)值,因此,這個(gè)不變式就可以保持成立。

協(xié)議

協(xié)議是Objective-C中一個(gè)有趣的概念,但是它們在Cocoa API中用得有限。之所以這樣做,有一個(gè)原因是協(xié)議有嚴(yán)格的設(shè)計(jì)要求。以某個(gè)含有十個(gè)方法的NSDataSource協(xié)議為例。如果某個(gè)開發(fā)人員遵循該協(xié)議并且實(shí)現(xiàn)其所有方法,而之后您又向該協(xié)議添加了一個(gè)新的方法,這就會破壞開發(fā)者和原有協(xié)議的一致性。因此,協(xié)議往往僅能包含它們***公開時(shí)所含有的方法集(除非您不期望其他開發(fā)者實(shí)現(xiàn)該協(xié)議)。因此,只有方法集不可能再增長時(shí),才應(yīng)使用協(xié)議。如果您必須擴(kuò)展某個(gè)協(xié)議,則您應(yīng)該添加一個(gè)新的協(xié)議,利用新協(xié)議來對原來的協(xié)議進(jìn)行擴(kuò)展,或者您可以把新方法添加在協(xié)議外部,并且在使用前檢查它是否存在。

基本上,上述的原因也可以解釋為何您不能使用常規(guī)協(xié)議來聲明委托方法。而把委托方法聲明為NSObjec上的范疇類— 即非正式的協(xié)議— 的另一個(gè)原因是我們可以選擇是否實(shí)現(xiàn)某個(gè)方法。

自動釋放的對象

返回對象值的方法或者函數(shù),如果它們不是用于創(chuàng)建對象或者復(fù)制對象(new,alloc,copy 以及這些方法的變體),則請務(wù)必讓其返回的對象可以autoreleased 。在此處,“自動釋放”并不一定表示對象應(yīng)該顯式自動釋放-即在返回對象之前,向?qū)ο蟀l(fā)送autorelease 消息。一般情況下,它僅表示返回值不是由調(diào)用者釋放。

出于性能方面的原因,請盡可能不要在方法實(shí)現(xiàn)中使用自動釋放的對象,特別是那些可能會在短時(shí)間內(nèi)頻繁執(zhí)行的代碼(例如在循環(huán)結(jié)構(gòu)中,循環(huán)次數(shù)未知并且可能是很多的情況)使用。舉個(gè)例子,對于下面的情況,您不應(yīng)該發(fā)送如下的消息:

  1. [NSString stringWithCharacters:]  

而是應(yīng)該發(fā)送下面的消息:

  1. [[NSString alloc] initWithCharacters:]  

當(dāng)您不再需要該字符串對象時(shí),請顯示地釋放它。但是,請記住有些時(shí)候方法或者函數(shù)會返回自動釋放的對象,這時(shí)您需要向?qū)ο蟀l(fā)送autorelease消息。

存取方法

在存取方法中作什么事情才是正確呢,這是個(gè)重要的問題。舉個(gè)例子,假設(shè)您在一個(gè)獲取方法中直接返回一個(gè)實(shí)例變量,而后立刻調(diào)用設(shè)置方法,則在釋放先前實(shí)例變量的時(shí)候就可能會有危險(xiǎn),因?yàn)樗锌赡馨涯胺祷氐闹到o釋放掉。

Cocoa框架的原則是讓設(shè)置方法自動釋放實(shí)例變量先前的值,但某些情況下,所涉及的某個(gè)設(shè)置方法會被頻繁的調(diào)用(例如在一個(gè)很密集的循環(huán)中),這時(shí)候Cocoa的原則就不適用了。但在實(shí)踐中,這種情況非常罕見,除非是一些底層的對象才會如此。另外,諸如NSAttributedString、NSArray、以及NSDictionary這樣的通用集合不會自動釋放對象,這主要是為了維護(hù)對象的存在時(shí)間。它們只是簡單地留存或者釋放其含有的對象。另外,它們也應(yīng)該對這一事實(shí)進(jìn)行歸檔,這樣客戶程序就可以了解這些對象的行為。

對于現(xiàn)在正在編寫的框架代碼, 我們建議在get方法中使用自動釋放的對象,因?yàn)檫@是最安全的方法:

  1. (NSString *)title {   
  2.     return [[instanceVar retain] autorelease];   
  3. }   
  4.     
  5. - (void)setTitle:(NSString *)newTitle {   
  6.     if (instanceVar != newTitle) {   
  7.         [instanceVar release];   
  8.         instanceVar = [newTitle copy];   
  9.         // or retain, depending on object & usage   
  10.     }   
  11. }  

另外,我們還需要考慮設(shè)置方法是使用copy方式還是使用retain方式。如果您所感興趣的是對象的值而非實(shí)際對象本身,則請使用copy方式。一個(gè)一般性的經(jīng)驗(yàn)法則是對實(shí)現(xiàn)NSCopying協(xié)議的對象使用copy方式(您不應(yīng)該在運(yùn)行時(shí)檢測對象是否實(shí)現(xiàn)NSCopying協(xié)議,而應(yīng)該直接查找參考文檔)。通常情況下,諸如字符串、顏色、URL這樣的對象應(yīng)該能被復(fù)制;而像視圖、窗口這樣的對象則應(yīng)該可以被保持。而至于其他的對象(例如數(shù)組),是使用copy還是使用retain,則要根據(jù)具體情況決定。

小結(jié):Cocoa 編碼指南 框架開發(fā)者使用技巧和技術(shù)的內(nèi)容介紹完了,希望本文對你有所幫助!關(guān)于Cocoa 編碼指南的更多內(nèi)容請參與編輯推薦。

責(zé)任編輯:zhaolei 來源: 互聯(lián)網(wǎng)
相關(guān)推薦

2022-01-18 23:26:45

開發(fā)

2011-06-17 16:23:49

Cocoa蘋果

2011-07-07 10:07:19

Cocoa 框架

2011-07-07 10:29:35

Cocoa 方法 框架

2011-07-07 10:39:07

Cocoa 函數(shù)

2018-03-27 23:25:40

Paddle

2011-04-02 13:44:08

2015-10-16 09:59:52

SwiftCocoa

2015-07-20 09:16:42

iOSWatchKit開發(fā)

2024-07-08 10:51:16

2019-11-14 14:44:32

開發(fā)者工具

2024-02-01 09:37:42

Kubernetes服務(wù)網(wǎng)格? 命令

2011-07-07 13:51:24

Cocoa 框架

2024-05-07 08:45:16

OpenAILlamaIndex大語言模型

2019-08-16 10:55:37

開發(fā)者技能AI

2010-07-29 17:15:55

Flex

2011-06-17 15:57:46

CocoaXcode蘋果

2023-05-08 15:59:27

UI自動化腳本鴻蒙

2022-01-02 23:26:08

開發(fā)SDK Sentry

2015-04-14 09:33:17

WatchKitAPP
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 日本一区二区视频 | 欧美一级精品片在线看 | 国产成人免费视频网站高清观看视频 | 99在线播放 | 亚洲视频在线观看免费 | 精品在线视频播放 | 成人伊人| 久久精品视频91 | 人人擦人人 | 亚洲精品99| 日韩成人在线电影 | 玖玖综合在线 | 亚洲精品视频在线 | www久久久| 男女午夜免费视频 | 久久综合狠狠综合久久综合88 | 毛片a级| 国产精品亚洲精品 | 我想看一级黄色毛片 | 欧美日韩在线视频一区二区 | a视频在线 | 欧美日韩亚洲在线 | 97超碰站| 久久黄色网 | 99久久精品免费看国产小宝寻花 | 国内av在线 | 国产激情一区二区三区 | 成人水多啪啪片 | 久久在线 | 亚洲成人精品一区二区 | 日韩中文一区 | 欧美一区二区三区高清视频 | 亚洲精品小视频在线观看 | 日韩最新网址 | 国产精品久久一区二区三区 | 成人欧美一区二区三区黑人孕妇 | 成人h动漫亚洲一区二区 | 天天干天天干 | 精品久久网 | 午夜在线免费观看 | 久久国产一区二区三区 |