第三章 接口與API設(shè)計(jì)(EffectiveObjective-C)

1 使用前綴避免命名空間沖突

  • 命名沖突,應(yīng)用程序鏈接的時(shí)候會(huì)報(bào)錯(cuò)
    duplicate symbol _OBJC_METACLASS_$_EOCTheClass in: build/somthing.o
    在運(yùn)行期載入了含有重名類的程序庫(kù),"動(dòng)態(tài)加載"遭遇"重名符號(hào)錯(cuò)誤",會(huì)導(dǎo)致程序崩潰
  • 不僅是類名,應(yīng)用程序中的所有名稱都應(yīng)加前綴,如果要為既有類新增"分類"(category),那么一定要給"分類"及"分類"中的方法加上前綴
  • 如果用第三方庫(kù)編寫自己的代碼,并準(zhǔn)備將其發(fā)布為程序庫(kù)供其他人開發(fā)應(yīng)用程序所用.
    這是應(yīng)該給你所用的那一份第三非苦代碼加上你自己的前綴.
    例如:你準(zhǔn)備發(fā)布的程序庫(kù)叫做EOCLibrary.

2 提供"全能初始化方法"

為對(duì)象提供必要信息以便其完成工作的初始化方法叫做"全能初始化方法"
UITableViewCell,在初始化該類對(duì)象時(shí),需要指明其樣式以及標(biāo)識(shí)符
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(nullable NSString *)reuseIdentifier
如果創(chuàng)建類實(shí)例的方式不止一個(gè),那么這個(gè)累就會(huì)有很多個(gè)初始化方法,不過(guò)仍然要在其中選定一個(gè)作為全能初始化方法,令其他初始化方法都來(lái)調(diào)用他
好處:當(dāng)?shù)讓訑?shù)據(jù)存儲(chǔ)機(jī)制改變時(shí),只需修改此方法的代碼就好,無(wú)須改變其他初始化方法

3 現(xiàn)實(shí)description方法

description:在NSObject協(xié)議中,自定義NSLog方法返回的字符串
debugDescription:在NSObject協(xié)議中,自定義在控制臺(tái)通過(guò)po命令輸出的的字符串

4 盡量使用不可變對(duì)象

  • 設(shè)計(jì)類的時(shí)候,應(yīng)充分應(yīng)用屬性來(lái)封裝數(shù)據(jù),而在使用屬性時(shí),則可將其聲明為"只讀"(read-only).
    默認(rèn)情況屬性是"可讀可寫"(read-write).這樣設(shè)計(jì)出來(lái)的類是"可變的".
    在編程實(shí)踐中,則應(yīng)該盡量把對(duì)外公布出來(lái)的屬性設(shè)為只讀,而且只在確有必要時(shí)才將屬性對(duì)外公布
@interface EOCPointOfInterest : NSObject
@property (nonatomic, copy,readonly) NSString *indentifier;
@property (nonatomic, copy,readonly) NSString *title;
@end
  • 有時(shí)可能想要修改封裝在對(duì)象內(nèi)部的數(shù)據(jù),但是卻不想令這些數(shù)據(jù)為外人所改動(dòng).這個(gè)時(shí)候,通常做飯是在對(duì)象內(nèi)部將readOnly屬性重新什么為readwrite,當(dāng)然屬性是nonatomic的,那么這樣做可能會(huì)產(chǎn)生"競(jìng)爭(zhēng)條件"(race condition).可以通過(guò)"派發(fā)隊(duì)列"等手段,講數(shù)據(jù)存取設(shè)為同步操作
#import "EOCPointOfInterest.h"
@interfaceEOCPointOfInterest ()
@property (nonatomic, copy,readwrite) NSString *indentifier;
@property (nonatomic, copy,readwrite) NSString *title;
@end

@implementation EOCPointOfInterest
@end
  • 不要把可變的collection作為屬性公開,而應(yīng)該提供相關(guān)方法,以此修改對(duì)象中的可變collection
    Person有個(gè)friends的集合屬性
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, strong,readonly) NSSet *friends;
- (void)addFriend:(Person*)person;
- (void)removeFriend:(Person*)person;
@end

@implementation Person{    
  NSMutableSet *_internalFriends;
}

- (NSSet *)friends{    
  return [_internalFriendscopy];
}
- (void)addFriend:(Person *)person{   
    [_internalFriendsaddObject:person];
}
- (void)removeFriend:(Person *)person{ 
   [_internalFriendsremoveObject:person];
}
@end

5 使用清晰而協(xié)調(diào)的命名方式

方法與變量名使用"駝峰式大小寫命名法",變量名小寫字母開頭,其后每個(gè)單詞首字母大寫
類名首字母要大寫,其后每個(gè)單詞首字母大寫.
5.1 方法命名

  • 如果方法的返回值是新創(chuàng)建的,那么方法名的首個(gè)詞應(yīng)該是返回值類型,除非前面還有修飾語(yǔ)
  • 應(yīng)該把標(biāo)識(shí)參數(shù)類型的名詞放在參數(shù)前面
  • 如果方法要在當(dāng)前對(duì)象上執(zhí)行操作,那么就應(yīng)該包含動(dòng)詞,若執(zhí)行操作時(shí)還需要參數(shù),則應(yīng)該在動(dòng)詞
    后面加上一個(gè)或多個(gè)名詞
  • 不要使用str這種簡(jiǎn)稱,應(yīng)該用string這樣的全稱
  • Boolean屬性應(yīng)加is當(dāng)前綴.如果某方法返回非屬性的Boolean值,那么應(yīng)該根據(jù)其功能選用
    has或is做前綴
  • 將get這個(gè)前綴留給哪些借由"輸出參數(shù)"來(lái)保存返回值的方法.

5.2 類與協(xié)議的命名
應(yīng)該為類與協(xié)議的名稱加上前綴,以避免命名控件沖突

6 為私有方法名加前綴

  • 一個(gè)類所做的事情通常都要比從外面看到的更多,編寫類的實(shí)現(xiàn)代碼時(shí),經(jīng)常要寫一些只有內(nèi)部使用
    的方法,建議為這種方法的名稱加上某些前綴, 這樣有助于調(diào)試, 這樣能很容易把公共與私有方法分開
  • 為私有方法添加前綴的好處二:修改其名稱或簽名之前要三思,公共API不便輕易改動(dòng)(影響面廣)
  • 具體使用何種前綴根據(jù)個(gè)人喜好,其中最好包含下劃線與字母, 如p_作為前綴
@interface EOCObject : NSObject
- (void)publicMethod;
@end
@implementation EOCObject
- (void)publicMethod{}
- (void)p_privateMthod{}
@end
  • 不要單用一個(gè)下劃線做私有方法的前綴,因?yàn)檫@種做法是預(yù)留給蘋果的

7 理解Objective-C 錯(cuò)誤類型

7.1 Objective-C:只在極其嚴(yán)重的錯(cuò)誤下拋出異常,拋出異常之后,無(wú)需考慮回復(fù)問(wèn)題,而且應(yīng)用程序此時(shí)也應(yīng)該退出
7.2 在非致命錯(cuò)誤:Objective-C所采用的方式是令方法返回nil/0. 或是使用NSError,以表明其中有錯(cuò)誤發(fā)生
7.3 NSError對(duì)象里封裝了三條消息

  • Error domain:錯(cuò)誤范圍,也就是產(chǎn)生錯(cuò)誤的根源.類型為字符串,通常用一個(gè)特有的全局變量來(lái)定義
  • Error code:錯(cuò)誤碼,類型為這個(gè)整數(shù).用意指明具體發(fā)生了何種錯(cuò)誤,通常采用enum來(lái)定義
  • User info:用戶信息,類型為字典,關(guān)于錯(cuò)誤的額外描述,包含一段"本地化描述"
    NSError第一種常見用法就是通過(guò)協(xié)議,來(lái)傳遞錯(cuò)誤.有錯(cuò)誤發(fā)生時(shí),當(dāng)前對(duì)象會(huì)把錯(cuò)誤信息經(jīng)由協(xié)議中的某個(gè)方法傳遞給委托對(duì)象(delegate)
    NSError第二種常見用法:經(jīng)由方法的"輸出參數(shù)"返回給調(diào)用者.
- (BOOL)doSomething:(NSError *__autoreleasing *)error{
  //do somethong that may cause an error   
 if (/*there was an error*/) {
        if (error) {
          *error = [NSErrorerrorWithDomain:domaincode:codeuserInfo:userInfo];
        }        
      returnNO;  
  }   
   returnYES;
}

傳遞給方法的參數(shù)是個(gè)指針,而該指針本事又指向另外一個(gè)指針,而該指針本身又指向另外一個(gè)指針,
那個(gè)指針指向NSError對(duì)象,或者也可以把他當(dāng)成一個(gè)直接指向NSError對(duì)象的指針.這樣一來(lái),就可以經(jīng)由
"輸出參數(shù)"把NSError對(duì)象傳遞給調(diào)用者

NSError *error=nil;
[selfdoSomething:&error];

8 理解NSCoping協(xié)議

如果想自己的類支持拷貝操作,那就要實(shí)現(xiàn)NSCopying協(xié)議,該協(xié)議只有一個(gè)方法
- (id)copyWithZone:(NSZone *)zone;
long long age,會(huì)據(jù)此把內(nèi)存分成不同的"區(qū)"(zone),而對(duì)象會(huì)創(chuàng)建在某個(gè)區(qū)里面,現(xiàn)在每個(gè)程序只有一個(gè)去,
"默認(rèn)區(qū)"(default zone).所以在實(shí)現(xiàn)這個(gè)方法的時(shí)候,不用考慮參數(shù)zone.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容