用前綴避免命名空間沖突
Objective-C沒有其他語言的內(nèi)置的命名空間(namespace)结序,所以在起名時就要設(shè)法避免 潛在的命名沖突暂殖。如果發(fā)生了naming clash(命名沖突)朝刊,那么程序的鏈接過程就會報錯。
- 選擇與你公司韭赘、應(yīng)用程序或二者皆有關(guān)聯(lián)的名稱作為類名的前綴,并在所有代碼中均使用這一前綴势就。
Apple宣稱其保留使用所有“兩字母前綴”(two-letter prefix)的權(quán)利泉瞻,也就是說自己選用的前綴應(yīng)該是三個字母。
- 若自己所開發(fā)的程序庫中用到了第三方庫苞冯,則應(yīng)為其中的名稱加上前綴袖牙。
提供“指定初始化方法”
什么是“指定初始化方法”,就是可謂對象提供必要信息以便其能完成工作的初始化方法舅锄。
??:在初始化UITabableViewCell的時候鞭达,需要指明style以及identifier,用來重復(fù)利用皇忿。
- 在類中提供一個指定初始化方法畴蹭,并于文檔里指明。其他初始化方法均應(yīng)調(diào)用此方法鳍烁。
如果一個類有多個初始化方法叨襟,不過仍然要在其中選定一個作為指定初始化方法,令其他初始化方法都來調(diào)用它幔荒。NSDate就是個??:
- (id)init;
- (id)initWithString:(NSString *)string;
- (id)initWithTimeIntervalSinceNow:(NSTimeInterval)seconds;
- (id)initWithTimeInterval:(NSTimeInterval)seconds sinceDate:(NSDate *)refDate;
- (id)initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)seconds;
- (id)initWithTimeIntervalSince1970:(NSTimeInterval)seconds;
在上面幾個方法中糊闽,“initWithTimeIntervalSinceReferenceDate:”是指定初始化方法梳玫,換而言之,其余的方法都要調(diào)用它右犹,并且也只有這個方法中才會存儲內(nèi)部數(shù)據(jù)汽纠。這樣做的好處就是,當(dāng)需要改變底層數(shù)據(jù)存儲機制時傀履,只需要修改此方法的代碼就好了虱朵,無須改動其他初始化方法。
- 若指定初始化方法和父類不同钓账,則需覆寫父類中對應(yīng)的方法碴犬。
- 如果父類的初始化方法不適用于子類,那么應(yīng)該覆寫這個父類方法梆暮,并在其中拋出異常服协。
實現(xiàn)description方法
- 實現(xiàn)description方法返回一個有意義的字符串,用以描述該實例啦粹。
在調(diào)試程序時偿荷,經(jīng)常需要打印并查看對象信息,最常用的做法就是:
NSLog(@"object = %@", object);
在構(gòu)建需要打印到日志的字符串時唠椭,object對象會收到desciption消息跳纳,該方法所返回的描述信息將取代“格式字符串”(format string)里的"%@"。??:
NSArray *object = @[@"A string", @(123)];
NSLog(@"object = %@", object);
//output:object = ( "A string", 123 )
但是贪嫂,如果在自定義類上這么做寺庄,輸出的信息卻是這樣的:
object = <MSTPerson: 0x3fd8a1377299>
這個時候就可以通過覆寫description方法來獲取更多的信息,??:
按照上面的代碼來寫力崇,那么MSTPerson就會出書如下格式的信息:
但是這里建議斗塘,在新實現(xiàn)的description方法中,也應(yīng)該像默認(rèn)的實現(xiàn)那樣亮靴,打印出類的名字和地址馍盟。
有個簡單的方法,可以在description中輸出很多互不相同的信息茧吊,那就是借助NSDictionary類的description方法贞岭。
??,下面這個類表示某個地點的名稱和地理坐標(biāo):
- 若想在調(diào)試時打印出更詳盡的對象描述信息饱狂,則應(yīng)實現(xiàn)debugDescription方法曹步。
都知道在打斷點的地方LLDB的"po"命令可以完成打印工作,而打印出來的內(nèi)容就是所打印的類的debugDescription方法返回的字符串休讳。如果想打印出更具體的指令讲婚,那么只需要像上面的做法一樣,更新debugDescription方法俊柔。
以MSTLocation為??:
output
盡量使用不可變對象
在使用屬性時筹麸,可以將其聲明為readonly活合,但是默認(rèn)的情況下,屬性是readwrite物赶,這樣都是可變的白指。但是一般的情況下,我們要建模的數(shù)據(jù)未必需要改變酵紫。
在具體的編程中告嘲,應(yīng)該盡量把對外公布出來的屬性設(shè)為只讀,而且只在確有必要時才將屬性對外公布奖地。??橄唬,要編寫一個類來處理地圖上的景點,這些點的數(shù)據(jù)通過某個網(wǎng)絡(luò)服務(wù)來獲取参歹。一開始寫出來的代碼也許就是:
但是這些屬性都是在外部不需要更改的仰楚,所以應(yīng)該這樣寫:
雖然沒有setter方法,但是仍要指定內(nèi)存管理語義(strong, weak之類)的原因就是這樣做以后更改為readwrite更方便犬庇。
- 若某屬性僅可用于對象內(nèi)部修改僧界,則在“class-continuation分類”中將其由readonly屬性擴展為readwrite屬性。
如果該屬性是nonatomic的臭挽,這樣做可能會產(chǎn)生“競爭條件”(race condition)捂襟。在對象內(nèi)部寫入某屬性時,對象外的observer也許正在讀取該屬性埋哟。想要避免這個問題笆豁,可以在必要時通過“派發(fā)隊列”(dispatch queue)等手段,將(包括對象內(nèi)部的)所有數(shù)據(jù)存取操作都設(shè)為同步操作赤赊。
??:
MSTPointOfInterest.m
現(xiàn)在,只能在內(nèi)部設(shè)置屬性值了煞赢,但是在外部還是可以通過KVC的方式來設(shè)置這些屬性值抛计。
- 不要把可變的collection作為屬性公開,而應(yīng)提供相關(guān)方法照筑,以此修改對象中的可變collection吹截。
??:
MSTPerson.m
當(dāng)然也可以用NSMutableSet來實現(xiàn)friends屬性,這樣就可以不借助"addFriend:"和"removeFriends:"方法直接操作凝危。但是這樣過分解耦(decouple)數(shù)據(jù)的做法很容易出bug波俄。
還需要強調(diào)的一點就是:不要在返回的對象上查詢類型以確定其是否可變。