前言
首先回顧下前面兩篇文章的內(nèi)容。
- 熟悉
OC<一>中提到暮刃,在OC語言的起源藐唠,OC語言為C語言的超集帆疟,所以可以容納所有的C語言的語法。以及OC語言所采用的消息結(jié)構(gòu)宇立。從語言特性上來說對于引入頭文件可以使用向前聲明踪宠,少用#define以及多用枚舉等內(nèi)容。 - 熟悉OC<二>圍繞著對象妈嘹、消息還有運行期詳細闡述了類和對象的本質(zhì)柳琢,消息分發(fā)系統(tǒng)的工作過程,以及OC作為動態(tài)綁定的語言润脸,具備的語言特點柬脸。
接下來文章將從OC語言的重點語法方面進行總結(jié),以及好的編程風格和注意事項進行一些歸納毙驯。
第一倒堕、 命名和API的設計
1. 為何要注重命名
- OC是“動態(tài)綁定”的語言,采用“消息結(jié)構(gòu)”爆价,OC中沒有命名空間的概念垦巴,所以OC語言的命名相對于JAVA語言和C++等面向?qū)ο蟮恼Z言在命名上就需要更加注意,以解決命名沖突的問題铭段。
- 另外更好的命令骤宣,能夠讓代碼更加易讀。這是一個優(yōu)秀程序員的基本素養(yǎng)序愚。
2. 命名的注意事項
-
首先新建Xcode工程的時候,如果你用過版本早點的Code應該會發(fā)現(xiàn)現(xiàn)在新建的工程沒有出現(xiàn)Classes Prefix的輸入項了憔披,到哪里去了,請看下圖爸吮。
- 關于上面提到的類前綴芬膝,一般選擇與公司、應用程序相關聯(lián)的為宜拗胜。而且應該一般選用3個大寫字母蔗候。(PS: 因為Apple官方宣傳其保留使用所有"兩個字母前綴"的權(quán)利,所以一般我們選擇3個字母埂软。 比如:你自己寫了一個網(wǎng)絡請求TWRequest锈遥,然后剛好過了一段時間Apple官方推出新的框架TWRequest專門用來封裝請求,那么就會出現(xiàn)沖突)
- ClassesPrefix需要增加前綴勘畔,此外對于分類Category也需要所灸。避免和他人的代碼整合的情況下出現(xiàn)沖突。
- 如果自己所開發(fā)的應用程序中用到了第三方庫炫七,那么請也其前面加上前綴爬立,雖然麻煩,但是若能避免潛在命名沖突還是值得的万哪。(如果是通過cocoapods集成的侠驯,那么筆者認為只需要的md文件上說明讓用戶去集成也是不錯的)抡秆。
- OC的方法名雖然繁冗,但是十分清晰吟策,從C++或者JAVA切換過來儒士,也許剛開始不好適應,但是也請寫完整檩坚。如下例子中OC的方法名雖然很長着撩,但是意思更加明確,可讀性更強匾委。
//比如
Rectangle* aCppRectangle = new Rectangle(5.0f, 10.0f); //其他語言
Rectangle* aOcRectangle = [[Rectangle alloc] initWithWidth:5.0f
height:10.0f]; //OC語言
- 關于私有方法的命名拖叙,OC是語言是沒有辦法將某個方法標志為私有,每個對象都可以響應任何的消息赂乐。所以開發(fā)者應該在命名慣例上體現(xiàn)出“私有方法”的語義薯鳍。由于蘋果公司喜歡對于私有的變量和方法采用下劃線開頭,所以筆者認為沪猴,對于私有的方法辐啄,我們應該采用類似于“p_”的前綴,以避免覆蓋父類的私有方法运嗜。
- 如果方法的返回值是新創(chuàng)建的壶辜,那么方法名的首個詞應該返回值的類型,除非前面還有修飾語担租。
- 應該把表示參數(shù)類型的名詞放在參數(shù)的前面砸民。
- 如果方法要在當前的對象上執(zhí)行操作,那么應該包含動詞奋救,如果還需要參數(shù)岭参,則應該在動詞后面加上一個或者多個名詞。
- 盡量不要使用縮寫而是使用全稱尝艘⊙莺睿‘
- Boolean類型的屬性返回應用is前綴,如果方法的返回是非屬性背亥,那么使用is或者has
- 將get這個前綴留給那些借由"輸出參數(shù)"來保存返回值的方法秒际。比如:把返回值填充到"C語言數(shù)組"中就可以使用該方法。
- 對于類和協(xié)議的命名狡汉,應該言簡意賅娄徊,從左到右讀起來像個日常用語最佳。
3. 設計類的時候盡可能使用不可變對象
也就是最好把一些不必要讓外界改變的屬性盾戴,設置成readonly寄锐。雖然根據(jù)KVC的特性,外界依然可以通過如下方法來改變數(shù)值,繞過了API方法橄仆,但是得自己承擔可能出現(xiàn)的問題剩膘。
此外設置成為readonly對于實現(xiàn)的代碼塊里面怎么進行屬性訪問,這個我們可以在"classes-continuatioon"分類里面將其轉(zhuǎn)換成readwrite沿癞。
最好不要把可變collection作為屬性公開援雇,而應提供相關的方法矛渴,以此修改對象中的可變collection椎扬。
[Person setValue:@"Marray" forKey:@"Name"]
4. 調(diào)試和異常處理
以下兩個在NSObject協(xié)議上的方法分別對應于NSLog的打印,以及通過調(diào)試器(LLDB)的命令行輸出打印具温。
description
debugDescription
OC語言中異常只用于處理嚴重的錯誤(fatal error, 致命錯誤)蚕涤,那么對其他錯誤(nonfatal error),OC中所采用的編程規(guī)范是令該方法返回nil/0,或者使用NSError,以表明其中錯誤的發(fā)生铣猩。
NSError的用法可以封裝成三條信息
Error domain: 錯誤發(fā)生的根源揖铜,通常用一個全局變量來定義。比如:"處理URL的子系統(tǒng)(URL-handling subsytem)"在從URL中解析或取得數(shù)據(jù)是出錯了达皿,那么久會使用NSURLErroDomain來表示錯誤范圍天吓。
Error code:(錯誤碼,類型為整數(shù))峦椰,特有的是錯誤代碼龄寞。通常也用enum來表示。例如HTTP請求汤功,就可以選用HTTP的狀態(tài)碼物邑,來作為錯誤碼。
User info(用戶信息滔金,類型為字典類型)色解,對于錯誤的本地化描述〔鸵穑或許還含有導致錯誤發(fā)生的另外一個錯誤科阎,經(jīng)由此種信息,尅將相關的錯誤串成一個錯誤鏈忿族。
在錯誤不那么嚴重的情況锣笨,可以指派“委托方法”來處理錯誤,也可以通過把錯誤信息放在NSError對象中肠阱,經(jīng)“輸出參數(shù)”返回給調(diào)用者票唆。
5. NSCopying協(xié)議
- 若想令自己縮寫的對象具有拷貝功能,則需是實現(xiàn)NSCopyint協(xié)議
如果自定義的對象分為可變版本與不可變版本屹徘,那么就要同時實現(xiàn)NSCopying與NSMutableCopyint協(xié)議 - 復制對象時需要決定采用淺拷貝還是深拷貝走趋,一般情況下是淺拷貝。
- 如果你縮寫的對象需要深拷貝噪伊,那么可考慮新增一個專門的執(zhí)行拷貝的方法簿煌。
第二氮唯、協(xié)議和分類
1. 關于協(xié)議
協(xié)議代理的設計模式可謂老生常談,這里就不詳細論述了姨伟,只指出幾個重要的點惩琉。
- 為了不產(chǎn)生"保留環(huán)"的問題,代理類型一定存儲模式一定要寫成 weak 或者 unsafe_unretain 當然后者的話就需要在對象銷毀后進行清空。weak有系統(tǒng)自動清空的功能夺荒,詳細見《熟悉OC一》瞒渠。
[_delegate responsesToSelector:@selector(XXXMethod)]
- 如上對于delegate中判定該方法是否存在非常重要,因為協(xié)議的optional類型技扼,代理對象雖然遵守協(xié)議但是未必有實現(xiàn)對應的方法伍玖。
必要的時候,可實現(xiàn)包含位段的結(jié)構(gòu)體剿吻,將委托對象是否能響應協(xié)議的方法緩存至其中窍箍。因為一般,代理對象是不會輕易的改變的丽旅。
struct data{
unsigned int didReceiveData : 1;
unsigned int didFailWithError : 1;
unsigned int didUpdateProgresTo : 1;
}_delegateFlag;
//從結(jié)構(gòu)體上可以看出didReceiveData均分別是占用1位的二進制位椰棘,所以只能取值0或者1,適合存放bool類型
2. 協(xié)議活學活用舉例
- 協(xié)議可在某種程度上提供匿名類型榄笙。具體的對象類型可以淡化成遵守某個協(xié)議的id類型
- 使用匿名對象隱藏對象類型或者(類名)
- 如果具體的類型不重要邪狞,重要的是對象能夠響應(定義在協(xié)議里的)特定方法,那么可以使用匿名對象來表示办斑。
3. 關于分類的優(yōu)勢
a. 使用分類機制可以把類的實現(xiàn)代碼劃分成多個易于管理的小塊外恕。
甚至可以將"私有"的方法歸入名字叫做private的分類中,以隱藏實現(xiàn)細節(jié)乡翅。
b. 使用分類方便調(diào)試鳞疲,比如:將對應的功能歸納到指定的分類,那么到時候編譯打包生成的符號表蠕蚜,將會是
[Person(Property) setCountry:@"China"];
很方便可以知道問題的所在區(qū)域尚洽。
c. 如果某個屬性在主接口上聲明為"只讀",而在類的內(nèi)部又要用設置方法來設置此屬性靶累,那么就在class-continuation中將其拓展為"可讀寫"
把私有方法原型聲明在"class-continuation"分類中腺毫。
d. 若是想使用的類,所遵守的協(xié)議不為人所知挣柬,則可于"class-continuation分類"中聲明
4. 使用分類應用的注意事項
- 給第三方類中添加分類時潮酒,總是應該給其名稱和方法上加上屬于你專用的前綴。
- 雖然從技術上來講可以在分類上新增屬性邪蛔,但是這樣會使內(nèi)存管理容易出錯急黎。
- 將封裝數(shù)據(jù)的所有的屬性都定義在主接口里
- 在class-continuation分類之外的其他分類,盡可能不要定義屬性。
- 通過class-continuation分類中可以添加實例變量勃教。
- 如果某個屬性在主接口上聲明為"只讀"淤击,而在類的內(nèi)部又要用設置方法來設置此屬性,那么就在class-continuation中將其拓展為"可讀寫"
把私有方法原型聲明在"class-continuation"分類中故源。 - 若是想使用的類污抬,所遵守的協(xié)議不為人所知,則可于"class-continuation分類"中聲明