【iOS 搭建基礎框架】編碼規範 (程式碼格式篇)

Bit俠發表於2018-01-24

本篇是 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) {
        // ...
    }];
複製程式碼

資料結構的字面量寫法

應該使用可讀性更好的字面量來構造NSArrayNSDictionary等資料結構,避免使用冗長的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) {
	...	
}
複製程式碼

哥們,都浪到這了,順手點個贊❤️唄~

參考文件

相關文章