第一條:
1轰枝、oc使用動態(tài)綁定的消息結(jié)構(gòu)捅彻,也就是說,在運(yùn)行時(shí)才會檢查對象類型鞍陨。接受一條消息之后,究竟應(yīng)該執(zhí)行何種代碼从隆,由運(yùn)行期環(huán)境而非編譯器來決定诚撵。
第二條:
1、在可能的情況下键闺,頭文件中盡量少引用其他頭文件寿烟,而是用@class 來向前聲明,這樣可以降低類之間的耦合辛燥,減少編譯時(shí)間筛武,防止循環(huán)引入。
2挎塌、有時(shí)候無法使用向前聲明徘六,比如要聲明某個(gè)類遵循一項(xiàng)協(xié)議。這種情況下榴都,盡量把“該類遵循某協(xié)議”的這條聲明移到”class-continuation分類“中待锈。如果不行的話就把協(xié)議單獨(dú)放在一個(gè)頭文件中,然后將其引入嘴高。
第三條:
1竿音、創(chuàng)建字符串、數(shù)值拴驮、數(shù)組春瞬、字典。時(shí)盡量使用字面量語法套啤,與創(chuàng)建此類對象的常規(guī)方法相比宽气,這么做更加簡明扼要。特別是NSArray和NSDictionary纲岭,使用字面量語法更為安全抹竹,在出錯(cuò)的地方更容易拋出錯(cuò)誤。
2止潮、應(yīng)該通過取下標(biāo)操作來訪問數(shù)組下標(biāo)或字典中的鍵鎖對應(yīng)的元素窃判。
第四條:
1、static修飾符意味著該變量僅在定義此變量的編譯單元中可見喇闸。編譯器沒收到一個(gè)編譯單元袄琳,就會輸出一份“目標(biāo)文件”询件。在OC的語境下,“編譯單元”一詞通常指每個(gè)類的實(shí)現(xiàn)文件(.m)唆樊。加入聲明變量時(shí)不加static宛琅,則編譯器會為它創(chuàng)建一個(gè)“外部符號”(external symbol)。此時(shí)若是另一個(gè)編譯單元中也聲明了同名變量逗旁,那么編譯器就會拋出一條錯(cuò)誤信息嘿辟。如果一個(gè)變量既聲明為static,又聲明為const片效,那么編譯器根本不會創(chuàng)建符號红伦,而是會想#define預(yù)處理指令一樣,把所有遇到的變量都替換為常值淀衣。注意const在語句中的位置昙读。應(yīng)該是放在變量名前,意義為此變量指針為不變常量膨桥。
2蛮浑、不要用預(yù)處理指令定義常量。這樣定義出來的常量不包含類型信息只嚣,編譯器只是會在編譯錢據(jù)此執(zhí)行查找替換搓作沮稚。即使有人從新定義了常量值,編譯器也不會產(chǎn)生警告信息介牙,這將導(dǎo)致應(yīng)用程序中的常量值不一致壮虫。
3、在實(shí)現(xiàn)文件中使用 static const來定義“只在編譯單元內(nèi)可見的常量”环础。由于此類常量不在全局符號表中囚似,所以無需為其名稱加前綴。
4线得、在頭文件中使用extern來聲明全局常量饶唤,并在相關(guān)實(shí)現(xiàn)文件中定義其值。這種常量出現(xiàn)在全局符號表中贯钩,所以其名稱應(yīng)加以區(qū)隔募狂,通常用與之相關(guān)的類名做前綴。
第五條:
1角雷、在使用枚舉變量時(shí)祸穷,如果不指定底層數(shù)據(jù)類型,則無法向前申明枚舉類型勺三,因?yàn)榫幾g器不清楚底層數(shù)據(jù)類型的大小雷滚,所以在用到此枚舉來行時(shí),也就不知道究竟應(yīng)該給變量分配多少空間吗坚。
2祈远、根據(jù)是否要將代碼按c++模式編譯呆万,NS_OPTIONS宏的定義方式也有所不同。如果不按c++編譯车份,那么其展開方式就和NS_ENUM相同谋减。若按照C++編譯,則展開后的代碼略有不同扫沼。原因在于出爹,用按位或運(yùn)算來操作兩個(gè)枚舉值時(shí),C++編譯模式的處理辦法與非C++模式不一樣缎除。作為選項(xiàng)的枚舉值經(jīng)常需要用按位或運(yùn)算來組合以政。在用或運(yùn)算操作兩個(gè)枚舉值時(shí),C++認(rèn)為運(yùn)算結(jié)果的數(shù)據(jù)類型應(yīng)該是美劇的底層數(shù)據(jù)類型伴找,也就是NSUInteger。而且C++不允許將這個(gè)底層類型“隱式轉(zhuǎn)換”為雷劇類型本身废菱。需要將按位或操作的結(jié)果顯示轉(zhuǎn)換過來技矮。所以,在C++模式下應(yīng)該用另一種方式定義NS_IPTIONS宏殊轴,以便省去類型轉(zhuǎn)換操作衰倦。鑒于此,犯事需要以按位或操作來組合的枚舉都應(yīng)使用NS_OPTIONS定義旁理。若是美劇不需要互相組合樊零,則應(yīng)使用NS_ENUM來定義。
3孽文、當(dāng)枚舉配合switch來使用的時(shí)候不要實(shí)現(xiàn)default分支驻襟,因?yàn)楫?dāng)后期增加枚舉選項(xiàng)時(shí),如果沒有default分支則會提示有分支未實(shí)現(xiàn)芋哭,如果實(shí)現(xiàn)了default分支這不會有此提示沉衣,鑒于此不要default分支會更加保證不容易出錯(cuò)。
4豌习、應(yīng)該用枚舉類表示狀態(tài)機(jī)的狀態(tài)、傳遞給方法的選項(xiàng)以及狀態(tài)嗎等值拔疚,給這些值起個(gè)易懂的名字肥隆。
第六條:
1稚失、如果使用了屬性的話嘱巾,那么編譯器就會自動便攜訪問這些屬性所需的方法憨琳,此過程叫做“自動合成”。這個(gè)過程由編譯器在編譯期執(zhí)行旬昭,所以編譯期里看不到這些“合成方法”的源代碼篙螟。
2、在并發(fā)編程中问拘,如果某操作具備整體性遍略,也就是說,系統(tǒng)其他部分無法觀察到其中間步驟所生成的臨時(shí)結(jié)果骤坐,而還能看到操作前與操作后的結(jié)果绪杏,那么該操作就是“原子的(atomic)”,或者說纽绍,該操作具備“原子性”(atomicity)蕾久。詳情參見:http://en.wikipedia.org/wiki/Atomicity_(programming)
3、NSString一般都使用copy來保護(hù)其封裝操作拌夏,因?yàn)閭鬟f給設(shè)置方法的新值有可能指向一個(gè)NSMutableString類的實(shí)例僧著。此時(shí)若是不拷貝字符串,那么設(shè)置完屬性之后障簿,字符串的值就可能會在對象不知情的情況下遭人更改盹愚。并且如果重寫了setter方法,需要在方法中保證其具備相關(guān)屬性所聲明的特質(zhì)站故。比如說皆怕,如果將某個(gè)屬性聲明為copy,那么久應(yīng)該在setter方法中拷貝相關(guān)對象西篓,否則會舞蹈該屬性的使用者愈腾。而且,若是不遵從這一約定污淋,還會令程序產(chǎn)生bug顶滩。
4、atomic和nonatomic的區(qū)別:具備atomic特質(zhì)的獲取方法會通過鎖定機(jī)制來確保其操作的原子性寸爆。也就是說礁鲁,如果兩個(gè)線程讀寫同一屬性,那么不論何時(shí)赁豆,總能看懂有效的屬性值仅醇。若是不加鎖的話(或者說使用nonatomic語義),那么其中一個(gè)線程正在改寫某屬性時(shí)魔种,另外一個(gè)線程也許會突然闖入析二,吧尚未修改好的屬性值讀取出來。發(fā)生這種情況時(shí),線程讀到的屬性值可能不太對叶摄。但是在實(shí)際的iOS開發(fā)過程中會發(fā)現(xiàn)属韧,其中所有的屬性都聲明為nonatomic。這樣做的歷史原因是:在iOS中使用同步鎖的開銷較大蛤吓,這會帶來性能問題宵喂。一般情況下并不要求屬性必須是“原子的”,因?yàn)檫@并不能保證“線程安全”(thread safety)会傲,若要實(shí)現(xiàn)“線程安全”的操作锅棕,還需要采用更為深層的鎖定機(jī)制才行。例如淌山,一個(gè)線程在連續(xù)多次讀取某屬性值的過程中有別的線程在同事改寫該值裸燎,那么即便將屬性聲明為atomic,也還是會督導(dǎo)不同的屬性值泼疑。因此德绿,開發(fā)iOS程序時(shí)一般都會使用nonatomic屬性。但是在開發(fā)mac os x程序時(shí)退渗,使用atomic屬性通常都不會有性能瓶頸脆炎。
5、開發(fā)iOS程序時(shí)應(yīng)該使用nonatomic屬性氓辣,因?yàn)閍tomic屬性會嚴(yán)重影響性能。
6袱蚓、在設(shè)置屬性鎖對應(yīng)的實(shí)例變量時(shí)钞啸,一定要罪從該屬性鎖聲明的語義。