本篇是 iOS 搭建基礎框架 系列,第一部分 編碼規範 的第二篇 程式碼格式篇。
其他相關文章傳送門如下:
本篇內容,摘取自蘋果、谷歌的文件翻譯,還有網上大神們貢獻的資料。
希望能讓你有所收穫,沒有收穫也沒關係,記得點贊~ ?
程式碼格式
縮排
不要在工程裡使用Tab鍵,使用空格來進行縮排。不要去修改Xcode > Preferences > Text Editing
裡的Tab和自動縮排的預設的 4 個空格設定,即使用 Xcode 的預設設定即可。
方法的書寫
一個典型的 Objective-C 方法應該是這樣的:
- (void)writeVideoFrameWithData:(NSData *)frameData timeStamp:(int)timeStamp {
...
}
複製程式碼
在-
和(void)
之間應該有一個空格,第一個大括號{
的位置在方法所在行的末尾,同樣應該有一個空格。
如果一個方法有特別多的引數或者名稱很長,應該將其按照:
來對齊分行顯示:
-(id)initWithModel:(IPCModle)model
ConnectType:(IPCConnectType)connectType
Resolution:(IPCResolution)resolution
AuthName:(NSString *)authName
Password:(NSString *)password
MAC:(NSString *)mac
AzIp:(NSString *)az_ip
AzDns:(NSString *)az_dns
Token:(NSString *)token
Email:(NSString *)email
Delegate:(id<IPCConnectHandlerDelegate>)delegate;
複製程式碼
在分行時,如果第一段名稱過短,後續名稱可以以Tab的長度(4個空格)為單位進行縮排:
- (void)short:(GTMFoo *)theFoo
longKeyword:(NSRect)theRect
evenLongerKeyword:(float)theInterval
error:(NSError **)theError {
...
}
複製程式碼
方法呼叫
方法呼叫的格式和書寫差不多,可以按照方法的長短來選擇寫在一行或者分成多行:
//寫在一行
[myObject doFooWith:arg1 name:arg2 error:arg3];
//分行寫,按照':'對齊
[myObject doFooWith:arg1
name:arg2
error:arg3];
//第一段名稱過短的話後續可以進行縮排
[myObj short:arg1
longKeyword:arg2
evenLongerKeyword:arg3
error:arg4];
複製程式碼
以下寫法是錯誤的:
//錯誤,要麼寫在一行,要麼全部分行
[myObject doFooWith:arg1 name:arg2
error:arg3];
[myObject doFooWith:arg1
name:arg2 error:arg3];
//錯誤,按照':'來對齊,而不是關鍵字
[myObject doFooWith:arg1
name:arg2
error:arg3];
複製程式碼
@public和@private標記符
@public和@private標記符應該以 一個空格 來進行縮排:
@interface MyClass : NSObject {
@public
...
@private
...
}
@end
複製程式碼
協議(Protocols)
在書寫協議的時候注意用<>
括起來的協議和型別名之間是沒有空格的,比如IPCConnectHandler()<IPCPreconnectorDelegate>
,這個規則適用所有書寫協議的地方,包括方法宣告、類宣告、例項變數等等:
@interface MyProtocoledClass : NSObject<NSWindowDelegate> {
@private
id<MyFancyDelegate> _delegate;
}
- (void)setDelegate:(id<MyFancyDelegate>)aDelegate;
@end
複製程式碼
閉包(Blocks)
根據block的長度,有不同的書寫規則:
- 較短的block可以寫在一行內。
- 如果分行顯示的話,block的右括號
}
應該和呼叫block那行程式碼的第一個非空字元對齊。 - block內的程式碼採用4個空格的縮排。
- 如果block過於龐大,應該單獨宣告成一個變數來使用。
^
和(
之間,^
和{
之間都沒有空格,引數列表的右括號)
和{
之間有一個空格。
//較短的block寫在一行內
[operation setCompletionBlock:^{ [self onOperationDone]; }];
//分行書寫的block,內部使用4空格縮排
[operation setCompletionBlock:^{
[self.delegate newDataAvailable];
}];
//使用C語言API呼叫的block遵循同樣的書寫規則
dispatch_async(_fileIOQueue, ^{
NSString* path = [self sessionFilePath];
if (path) {
// ...
}
});
//較長的block關鍵字可以縮排後在新行書寫,注意block的右括號'}'和呼叫block那行程式碼的第一個非空字元對齊
[[SessionService sharedService]
loadWindowWithCompletionBlock:^(SessionWindow *window) {
if (window) {
[self windowDidLoad:window];
} else {
[self errorLoadingWindow];
}
}];
//較長的block引數列表同樣可以縮排後在新行書寫
[[SessionService sharedService]
loadWindowWithCompletionBlock:
^(SessionWindow *window) {
if (window) {
[self windowDidLoad:window];
} else {
[self errorLoadingWindow];
}
}];
//龐大的block應該單獨定義成變數使用
void (^largeBlock)(void) = ^{
// ...
};
[_operationQueue addOperationWithBlock:largeBlock];
//在一個呼叫中使用多個block,注意到他們不是像方法那樣通過':'對齊的,而是同時進行了4個空格的縮排
[myObject doSomethingWith:arg1
firstBlock:^(Foo *a) {
// ...
}
secondBlock:^(Bar *b) {
// ...
}];
複製程式碼
資料結構的字面量寫法
應該使用可讀性更好的字面量來構造NSArray
,NSDictionary
等資料結構,避免使用冗長的alloc
,init
方法。
如果構造程式碼寫在一行,需要在括號兩端留有一個空格,使得被構造的元素於與構造語法區分開來:
//正確,在字面量的"[]"或者"{}"兩端留有空格
NSArray *array = @[ [foo description], @"Another String", [bar description] ];
NSDictionary *dict = @{ NSForegroundColorAttributeName : [NSColor redColor] };
//不正確,不留有空格降低了可讀性
NSArray* array = @[[foo description], [bar description]];
NSDictionary* dict = @{NSForegroundColorAttributeName: [NSColor redColor]};
複製程式碼
如果構造程式碼不寫在一行內,構造元素需要使用 兩個空格 來進行縮排,右括號]
或者}
寫在新的一行,並且與呼叫字面量那行程式碼的第一個非空字元對齊:
NSArray *array = @[
@"This",
@"is",
@"an",
@"array"
];
NSDictionary *dictionary = @{
NSFontAttributeName : [NSFont fontWithName:@"Helvetica-Bold" size:12],
NSForegroundColorAttributeName : fontColor
};
複製程式碼
構造字典時,字典的Key和Value與中間的冒號:
都要留有一個空格,多行書寫時,也可以將Value對齊:
//正確,冒號':'前後留有一個空格
NSDictionary *option1 = @{
NSFontAttributeName : [NSFont fontWithName:@"Helvetica-Bold" size:12],
NSForegroundColorAttributeName : fontColor
};
//正確,按照Value來對齊
NSDictionary *option2 = @{
NSFontAttributeName : [NSFont fontWithName:@"Arial" size:12],
NSForegroundColorAttributeName : fontColor
};
//錯誤,冒號前應該有一個空格
NSDictionary *wrong = @{
AKey: @"b",
BLongerKey: @"c",
};
//錯誤,每一個元素要麼單獨成為一行,要麼全部寫在一行內
NSDictionary *alsoWrong= @{ AKey : @"a",
BLongerKey : @"b" };
//錯誤,在冒號前只能有一個空格,冒號後才可以考慮按照Value對齊
NSDictionary *stillWrong = @{
AKey : @"b",
BLongerKey : @"c",
};
複製程式碼
nil檢查
因為在 Objective-C 中向nil物件傳送命令是不會丟擲異常或者導致崩潰的,只是完全的“什麼都不幹”,所以,只在程式中使用nil來做邏輯上的檢查。
另外,不要使用諸如nil == Object
或者Object == nil
的形式來判斷。
//正確,直接判斷
if (!objc) {
...
}
//錯誤,不要使用nil == Object的形式
if (nil == objc) {
...
}
複製程式碼
哥們,都浪到這了,順手點個贊❤️唄~