條件語句
總是要用大括號
尤達表達式
不推薦
nil 和 BOOL
不要直接把對象跟nil或YES,NO比較,用 if(!xx)來即可
黃金大道
即不要嵌套if語句,可以使用return語句避免增加循環(huán)的復(fù)雜度
即推薦:
- (void)someMethod {
if (![someOther boolValue]) {
return;
}
//Do something important
}
不推薦
- (void)someMethod {
if ([someOther boolValue]) {
//Do something important
}
}
其中有句原話是:
在使用條件語句編程時,代碼的左邊距應(yīng)該是一條“黃金”或者“快樂”的大道。
對黃金大道這個比喻不理解,不明白黃金大道的在這里的比喻。
但是上面的例子是比較清晰的。
復(fù)雜的表達式
if中的復(fù)雜表達式,提取出來賦值給BOOL,使之更清晰 。
BOOL nameContainsSwift = [sessionName containsString:@"Swift"];
BOOL isCurrentYear = [sessionDateCompontents year] == 2014;
BOOL isSwiftSession = nameContainsSwift && isCurrentYear;
if (isSwiftSession) {
// Do something very cool
}
三元運算符
三元運算符里的子句,應(yīng)該也只是求值后的變量,不要直接用復(fù)雜的句子。
推薦
result = a > b ? x : y;
不推薦
result = a > b ? x = c > d ? c : d : y;
另外,推薦更靈活地表達方式:
result = object ? : [self createObject];
不推薦
result = object ? object : [self createObject];
錯誤處理
有些方法通過參數(shù)返回 error 的引用,使用這樣的方法時應(yīng)當檢查方法的返回值,而非 error 的引用。
推薦:
NSError *error = nil; if (![self trySomethingWithError:&error]) { // Handle Error }此外,一些蘋果的 API 在成功的情況下會對 error 參數(shù)(如果它非 NULL)寫入垃圾值(garbage values),所以如果檢查 error 的值可能導(dǎo)致錯誤 (甚至崩潰)。
Case語句
switch語句里是枚舉變量時,建議不要用default,因為當枚舉增加時,這些switch語句會收到警告
使用枚舉變量時,建議使用新的宏- NS_ENUM()
命名
通用的約定
駝峰法命名
You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or mutableCopy).
常量
駝峰法,類名做前綴,盡量用常量類型少用宏
方法
- 方法名與方法類型 (-/+ 符號)之間應(yīng)該以空格間隔
- 方法段之間也應(yīng)該以空格間隔(以符合 Apple 風(fēng)格)
- 參數(shù)前應(yīng)該總是有一個描述性的關(guān)鍵詞。盡可能少用 "and" 這個詞
字面值
不推薦[@[] mutableCopy]這種寫法。
類
類名
- 類名應(yīng)該以三個大寫字母作為前綴
- 當你創(chuàng)建一個子類的時候,你應(yīng)該把說明性的部分放在前綴和父類名的在中間。如有一個
ZOCNetworkClient類,子類的名字會是ZOCTwitterNetworkClient
Initializer 和 dealloc
-
dealloc函數(shù)應(yīng)該放在文件的最前面,init方法跟在后面。 -
alloc和init方法解釋。
Designated 和 Secondary 初始化方法
- 一個類應(yīng)該有且只有一個 designated 初始化方法
- 子類的Designated Initializer應(yīng)該調(diào)用父類的Designated Initializer方法。
- 用
NS_DESIGNATED_INITIALIZER來指定為Designated Initializer(方法后加上該宏)。 - Secondary Initializer應(yīng)該調(diào)用Designated Initializer
- 初始化方法返回參數(shù)用instancetype替換id
- 類簇 (class cluster)的解釋
- 單例用
dispatch_once()替代@synchronized
屬性
- 命名用小寫字母開頭的駝峰命名
- 在init方法里要直接用實例變量,不要用set/get方法訪問屬性變量。因為子類可能重載屬性變量。
- 用點語法
- 屬性的參數(shù)應(yīng)該按照下面的順序排列: 原子性,讀寫 和 內(nèi)存管理
- NSString,NSArray,NSURLRequest等有可變對象的類,盡量用copy,防止用strong指向可變子類,導(dǎo)致值被修改出現(xiàn)問題
- 用懶加載(Lazy Loading)時,注意副作用,如get方法里修改了一些類的全局變量,導(dǎo)致加載時機不同出現(xiàn)問題
方法
- 用斷言
NSAssert()或NSParameterAssert()拋參數(shù)異常 - 私有變量和私有方法不要用
_前綴,蘋果已保留該前綴
相等性
當你要實現(xiàn)相等性的時候記住這個約定:你需要同時實現(xiàn)isEqual 和 hash方法。如果兩個對象是被isEqual認為相等的,它們的 hash 方法需要返回一樣的值。但是如果 hash 返回一樣的值,并不能確保他們相等。
Categories
category里的方法應(yīng)該用自己的小寫前綴加下劃線,如- (id)zoc_myCategoryMethod
Protocols
用協(xié)議提高代碼的復(fù)用性
NSNotification
通知名應(yīng)該用類名做前綴,用一個 Did/Will 這樣的動詞以及用 "Notifications" 后綴。如
// Foo.h
extern NSString * const ZOCFooDidBecomeBarNotification
// Foo.m
NSString * const ZOCFooDidBecomeBarNotification = @"ZOCFooDidBecomeBarNotification";
美化代碼
- 空格,這里說用四個空格替代TAB,但是一般文章都是推薦用TAB,因為可以根據(jù)編譯的設(shè)定而改變,所以這里存疑
- 方法的大括號和其他的大括號(if/else/switch/while 等) 總是在同一行開始
- 方法之間要有空行
- 參數(shù)換行
代碼組織
善用代碼塊
{}方法用
#pragma mark -組織分離-
當用
performSelector調(diào)用方法在ARC出現(xiàn)警告時,可用#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變量未使用,用該方法不提示警告)注釋分兩種
//和/** */。非公開、很短、顯而易見的函數(shù)一般用//,其它和對外暴露的一般用/** */
對象間的通訊
-
Block,這里說下“在 block 外定義一個 __weak 的 引用到 self,并在 block 內(nèi)部通過這個弱引用定義一個 __strong 的引用?!?/em>的情況。這種一般是需要持有self,但是又為了避免retain circle的情況。block內(nèi)的self強引用是Block執(zhí)行時創(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)引用,而再聲明一個strongSelf是因為一旦進入block執(zhí)行,就不允許self在這個執(zhí)行過程中釋放。block執(zhí)行完后這個strongSelf會自動釋放,沒有循環(huán)引用問題。
- 多重委托
面向切面編程
AOP,面向切面編程,統(tǒng)計與日志就是一個完美的例子。