條件語(yǔ)句
總是要用大括號(hào)
尤達(dá)表達(dá)式
不推薦
nil 和 BOOL
不要直接把對(duì)象跟nil或YES,NO比較褒纲,用 if(!xx)來(lái)即可
黃金大道
即不要嵌套if
語(yǔ)句,可以使用return
語(yǔ)句避免增加循環(huán)的復(fù)雜度
即推薦:
- (void)someMethod {
if (![someOther boolValue]) {
return;
}
//Do something important
}
不推薦
- (void)someMethod {
if ([someOther boolValue]) {
//Do something important
}
}
其中有句原話是:
在使用條件語(yǔ)句編程時(shí)双抽,代碼的左邊距應(yīng)該是一條“黃金”或者“快樂(lè)”的大道。
對(duì)黃金大道這個(gè)比喻不理解闲礼,不明白黃金大道的在這里的比喻牍汹。
但是上面的例子是比較清晰的。
復(fù)雜的表達(dá)式
if中的復(fù)雜表達(dá)式柬泽,提取出來(lái)賦值給BOOL慎菲,使之更清晰 。
BOOL nameContainsSwift = [sessionName containsString:@"Swift"];
BOOL isCurrentYear = [sessionDateCompontents year] == 2014;
BOOL isSwiftSession = nameContainsSwift && isCurrentYear;
if (isSwiftSession) {
// Do something very cool
}
三元運(yùn)算符
三元運(yùn)算符里的子句锨并,應(yīng)該也只是求值后的變量露该,不要直接用復(fù)雜的句子。
推薦
result = a > b ? x : y;
不推薦
result = a > b ? x = c > d ? c : d : y;
另外第煮,推薦更靈活地表達(dá)方式:
result = object ? : [self createObject];
不推薦
result = object ? object : [self createObject];
錯(cuò)誤處理
有些方法通過(guò)參數(shù)返回 error 的引用解幼,使用這樣的方法時(shí)應(yīng)當(dāng)檢查方法的返回值,而非 error 的引用包警。
推薦:
NSError *error = nil; if (![self trySomethingWithError:&error]) { // Handle Error }
此外书幕,一些蘋(píng)果的 API 在成功的情況下會(huì)對(duì) error 參數(shù)(如果它非 NULL)寫(xiě)入垃圾值(garbage values),所以如果檢查 error 的值可能導(dǎo)致錯(cuò)誤 (甚至崩潰)揽趾。
Case語(yǔ)句
switch語(yǔ)句里是枚舉變量時(shí)台汇,建議不要用default
,因?yàn)楫?dāng)枚舉增加時(shí),這些switch語(yǔ)句會(huì)收到警告
使用枚舉變量時(shí)篱瞎,建議使用新的宏- NS_ENUM()
命名
通用的約定
駝峰法命名
You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or mutableCopy).
常量
駝峰法苟呐,類(lèi)名做前綴,盡量用常量類(lèi)型少用宏
方法
- 方法名與方法類(lèi)型 (-/+ 符號(hào))之間應(yīng)該以空格間隔
- 方法段之間也應(yīng)該以空格間隔(以符合 Apple 風(fēng)格)
- 參數(shù)前應(yīng)該總是有一個(gè)描述性的關(guān)鍵詞俐筋。盡可能少用 "and" 這個(gè)詞
字面值
不推薦[@[] mutableCopy]
這種寫(xiě)法牵素。
類(lèi)
類(lèi)名
- 類(lèi)名應(yīng)該以三個(gè)大寫(xiě)字母作為前綴
- 當(dāng)你創(chuàng)建一個(gè)子類(lèi)的時(shí)候,你應(yīng)該把說(shuō)明性的部分放在前綴和父類(lèi)名的在中間澄者。如有一個(gè)
ZOCNetworkClient
類(lèi)笆呆,子類(lèi)的名字會(huì)是ZOCTwitterNetworkClient
Initializer 和 dealloc
-
dealloc
函數(shù)應(yīng)該放在文件的最前面,init
方法跟在后面粱挡。 -
alloc
和init
方法解釋赠幕。
Designated 和 Secondary 初始化方法
- 一個(gè)類(lèi)應(yīng)該有且只有一個(gè) designated 初始化方法
- 子類(lèi)的Designated Initializer應(yīng)該調(diào)用父類(lèi)的Designated Initializer方法。
- 用
NS_DESIGNATED_INITIALIZER
來(lái)指定為Designated Initializer(方法后加上該宏)询筏。 - Secondary Initializer應(yīng)該調(diào)用Designated Initializer
- 初始化方法返回參數(shù)用instancetype替換id
- 類(lèi)簇 (class cluster)的解釋
- 單例用
dispatch_once()
替代@synchronized
屬性
- 命名用小寫(xiě)字母開(kāi)頭的駝峰命名
- 在init方法里要直接用實(shí)例變量榕堰,不要用set/get方法訪問(wèn)屬性變量。因?yàn)樽宇?lèi)可能重載屬性變量嫌套。
- 用點(diǎn)語(yǔ)法
- 屬性的參數(shù)應(yīng)該按照下面的順序排列: 原子性逆屡,讀寫(xiě) 和 內(nèi)存管理
- NSString,NSArray,NSURLRequest等有可變對(duì)象的類(lèi)圾旨,盡量用copy,防止用strong指向可變子類(lèi)魏蔗,導(dǎo)致值被修改出現(xiàn)問(wèn)題
- 用懶加載(Lazy Loading)時(shí)砍的,注意副作用,如get方法里修改了一些類(lèi)的全局變量莺治,導(dǎo)致加載時(shí)機(jī)不同出現(xiàn)問(wèn)題
方法
- 用斷言
NSAssert()
或NSParameterAssert()
拋參數(shù)異常 - 私有變量和私有方法不要用
_
前綴挨约,蘋(píng)果已保留該前綴
相等性
當(dāng)你要實(shí)現(xiàn)相等性的時(shí)候記住這個(gè)約定:你需要同時(shí)實(shí)現(xiàn)isEqual 和 hash方法。如果兩個(gè)對(duì)象是被isEqual認(rèn)為相等的产雹,它們的 hash 方法需要返回一樣的值诫惭。但是如果 hash 返回一樣的值,并不能確保他們相等蔓挖。
Categories
category里的方法應(yīng)該用自己的小寫(xiě)前綴加下劃線夕土,如- (id)zoc_myCategoryMethod
Protocols
用協(xié)議提高代碼的復(fù)用性
NSNotification
通知名應(yīng)該用類(lèi)名做前綴,用一個(gè) Did/Will 這樣的動(dòng)詞以及用 "Notifications" 后綴瘟判。如
// Foo.h
extern NSString * const ZOCFooDidBecomeBarNotification
// Foo.m
NSString * const ZOCFooDidBecomeBarNotification = @"ZOCFooDidBecomeBarNotification";
美化代碼
- 空格怨绣,這里說(shuō)用四個(gè)空格替代TAB,但是一般文章都是推薦用TAB拷获,因?yàn)榭梢愿鶕?jù)編譯的設(shè)定而改變篮撑,所以這里存疑
- 方法的大括號(hào)和其他的大括號(hào)(if/else/switch/while 等) 總是在同一行開(kāi)始
- 方法之間要有空行
- 參數(shù)換行
代碼組織
善用代碼塊
{}
方法用
#pragma mark -
組織分離-
當(dāng)用
performSelector
調(diào)用方法在ARC出現(xiàn)警告時(shí),可用#pragma clang diagnostic
去除警告匆瓜,代碼示例:#pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" [myObj performSelector:mySelector withObject:name]; #pragma clang diagnostic pop
忽視未讀變量的方法:
#pragma unused (foo)
(如果foo變量未使用赢笨,用該方法不提示警告)注釋分兩種
//
和/** */
。非公開(kāi)驮吱、很短茧妒、顯而易見(jiàn)的函數(shù)一般用//
,其它和對(duì)外暴露的一般用/** */
對(duì)象間的通訊
-
Block,這里說(shuō)下“在 block 外定義一個(gè) __weak 的 引用到 self左冬,并在 block 內(nèi)部通過(guò)這個(gè)弱引用定義一個(gè) __strong 的引用桐筏。”的情況拇砰。這種一般是需要持有self梅忌,但是又為了避免retain circle的情況。block內(nèi)的self強(qiáng)引用是Block執(zhí)行時(shí)創(chuàng)建的除破,
示例代碼如下:@property (nonatomic,strong) NSString *testString; @property (nonatomic,copy) void(^BlockTest)(); self.testString = @"testststs"; __weak typeof(self)weakSelf = self; self.BlockTest = ^(){ __strong typeof(self)strongSelf = weakSelf; NSLog(@"%@",strongSelf.testString); }; self.BlockTest();
注:weakSelf是為了block不持有self牧氮,避免循環(huán)引用,而再聲明一個(gè)strongSelf是因?yàn)橐坏┻M(jìn)入block執(zhí)行皂岔,就不允許self在這個(gè)執(zhí)行過(guò)程中釋放蹋笼。block執(zhí)行完后這個(gè)strongSelf會(huì)自動(dòng)釋放展姐,沒(méi)有循環(huán)引用問(wèn)題躁垛。
- 多重委托
面向切面編程
AOP剖毯,面向切面編程,統(tǒng)計(jì)與日志就是一個(gè)完美的例子教馆。