Effective Object-C 52:15-22

三、接口與API設(shè)計(jì)

15. 用前綴避免命名空間沖突

  • 選擇公司、應(yīng)用程序、其一二之名作為類名的前綴,并在所有代碼均使用這一前綴
  • 為項(xiàng)目中使用第三方庫(kù)加上前綴。(一般不用)

OC 沒(méi)有內(nèi)置的命名空間(namespace)機(jī)制,所以如果命名重名,就會(huì)發(fā)送命名沖突(naming calsh)項(xiàng)目報(bào)錯(cuò)。

重命名符號(hào)錯(cuò)誤(duplicate symbol error)報(bào)錯(cuò):

duplicate symbol _OBJC_METACLASS_$_EOCTheClass in:
    build/something.o
    build/something_else.o
duplicate symbol _OBJC_CLASS_$_EOCTheClass in:
    build/something.o
    build/something_else.o

解決方案:

  1. 所有名稱都加上適量前綴。
  2. 使用3字母 != Apple Cocoa(兩字母前綴 two_letter prefix)。

16. 提供“全能初始化方法”

  • 在類中提供一個(gè)全能初始化方法,并在文檔中指明。其他初始化方法均調(diào)用次方法。
  • 若全能初始化方法與超類不同, 則需要覆寫(xiě)超類中對(duì)應(yīng)的方法
  • 超類的初始化不適用子類,應(yīng)該覆寫(xiě)超類的方法,并在其中拋出異常。

全能初始化(指定初始化方法)(designated initializer):對(duì)象提供必要信息以便其能完成工作的初始化方法。
這個(gè)類多個(gè)初始化方法,其他初始化方法調(diào)用全能初始化。

覆寫(xiě)父類的全能初始化方法并在其中拋出異常:

-(id) initWithWidth:(float)width andHeight:(float)height{
    @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Must use initWithDimension: instead." userInfo:nil];
}

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

  • 實(shí)現(xiàn)description方法返回有意義的字符串,用以描述該實(shí)例。
  • 調(diào)試時(shí)候打?。簩?shí)現(xiàn)debugDescription方法。

在類里添加實(shí)現(xiàn)方法 description、 debugDescription

-(NSString *)description{
    return [NSString stringWithFormat:@"%@, %@",[self class], self];
}
-(NSString *)debugDescription{
    return [NSString stringWithFormat:@"%@, %@",[self class], self];
}

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

  • 盡量創(chuàng)建不可變的對(duì)象。
  • 某些屬性僅可用于對(duì)象內(nèi)部修改,則在“calss-continuation 分類” 中將其由readonly屬性擴(kuò)張為readwrite屬性。
  • 不要把可變的collection作為屬性公開(kāi),而應(yīng)提供相關(guān)的方法,以此修改對(duì)象中可變的collection。

例子: 在類 head 里實(shí)現(xiàn)readonly 在“calss-continuation 分類” readwrite。

@interface CustomViewController:UIViewController

@property(nonatomic, copy, readonly) NSString* identifier;

@end

@interface CustomViewController ()

@property(nonatomic, copy, readwrite) NSString* identifier;

@end

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

  • 遵從標(biāo)準(zhǔn)的Object-C 命名規(guī)范。
  • 言簡(jiǎn)意駭,從左至右讀起來(lái)要像個(gè)日常用語(yǔ)(最好)
  • 不要使用縮略后的類型
  • 風(fēng)格符合自己的代碼或者集成的框架。

方法和命名:

  1. 駝峰式大小寫(xiě)命名發(fā)(camel casing):小寫(xiě)字母開(kāi)頭、其后沒(méi)有單詞首字母大寫(xiě)。
  2. 類名也用駝峰,不過(guò)都要首字母要大寫(xiě)。
方法命名例子:
+string
+stringWithString
+localizedStringWithFormat:
-lowercaseString
-intValue
-length
-lengthOfBytesUsingEncoding:
-getCharacters:range:
-(void)getCharacters:(unichar*)buffer range:(NSRange)aRange
-hasPrefix
-isEqualToString:
類和協(xié)議的命名:
  1. 加上前綴。 例如: UIView、UIViewController..
  2. 在類名后面加上Delegate 例如:UITableViewDelegate

20. 為私有方法添加前綴

  • 私有方法加上前綴區(qū)別公有方法
  • 不要單用"_" 來(lái)做私有方法的前綴,這種做法是預(yù)留給apple 公司的。

私有方法添加前綴: "p_"

-(void)p_privateMethod{}

21. 理解Object-C 錯(cuò)誤模型

  1. 只在及其罕見(jiàn)的情況下才會(huì)拋出異常,程序直接退出。
  2. 不那么嚴(yán)重的錯(cuò)誤: 方法放回 nil/0, 或是使用NSError 表明有錯(cuò)誤發(fā)生。

NSError 三條信息:

  1. Error domain (錯(cuò)誤范圍, type : NSString)
  2. Error code (錯(cuò)誤碼, type: int)
  3. user info (用戶信息, type: dictionary)

NSError 常見(jiàn)用法

1.由(delegate) 來(lái)傳遞

-(void)connection:(NSURLConnection*) connection didFailWithError:(NSError*) error

2.由方法的“輸出參數(shù)” 放回給調(diào)用者,不僅能通過(guò)返回值判斷是否成功,還通過(guò)NSError來(lái)判定

-(BOOL)doSomething:(NSError**)error
NSError *error = nil;
BOOL ret = [object doSomething:&error];
if(error){
    //There was an error
}

BOOL ret = [object doSomething:nil];
if (ret){
    //there was an error
}

3.例子

-(BOOL)doSomething:(NSError **)error{
    //Do Something that my cause an error
    if(/* there was an error */){
        if (error){
        //Pass the 'error' through the out-parameter
            *error = [NSError errorWithDmain:domain code:code userinfo:userInfo];
        }   
        return NO;
    }else {
        return YES;
    }
    
}

22. 理解NSCoping 協(xié)議

  • 若自定義對(duì)象具有拷貝功能,需實(shí)現(xiàn)NSCopying 協(xié)議
  • 根據(jù)對(duì)象類型 : 可變、不可變 -> NSCopying 與 NSMuatbleCoping
  • 淺拷貝、深拷貝(若需要,則考慮新增一個(gè)專門執(zhí)行深拷貝的方法), 一般情況應(yīng)該盡量使用淺拷貝。

兩個(gè)拷貝協(xié)議 NSCopying、NSMutableCopying:


- (id)copyWithZone:(nullable NSZone *)zone;

- (id)mutableCopyWithZone:(nullable NSZone *)zone;

例子:

-(id)copyWithZone:(NSZone *)zone{
     Person* copy = [[[self class] allocWithZone:zone] initWithFirstName:_firstName];
     copy->_friends = [_friends mutableCopy];
    return
}

"->" 語(yǔ)法:內(nèi)部使用實(shí)例變量。

最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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