ios 編碼規範

正文:
格式化代碼

指針“*”號的位置
如:NSString *varName;

空格 VS tabs
只允許使用空格,將編輯器設置爲1TAB = 2個字符縮進

每行的長度

  • ▪  每行最多不得超過100個字符

  • ▪  15Macbook Pro的大小,每行100個字符時能最大化地同時容下編輯器和iPhone模擬器

  • ▪  Google80字符的標準有點少,這導致過於頻繁的換行(Objectve-C的代碼一般都很長)

  • ▪  通過 “Xcode => Preferences => TextEditing => 勾選Show Page Guide / 輸入

    100 => OK” 來設置提醒方法的聲明和定義

  • ▪  - OR + 和返回值之間留1個空格,方法名和第一個參數間不留空格。如:- (void)doSomethingWithString:(NSString *)theString {

    ...}

  • ▪  當參數過長時,每個參數佔用一行,以冒號對齊。如:- (void)doSomethingWith:(GTMFoo *)theFoo

                              rect:(NSRect)theRect
                          interval:(float)theInterval {
    

    ...}

  • ▪  如果方法名比參數名短,每個參數佔用一行,至少縮進4個字符,且爲垂直對齊(而非使用冒號對齊)。如:
    - (void)short:(GTMFoo *)theFoo

               longKeyword:(NSRect)theRect
    
               evenLongerKeyword:(float)theInterval {
             ...
    

    }

    方法的調用

  • ▪  調用方法沿用聲明方法的習慣。例外:如果給定源文件已經遵從某種習慣,繼續遵從那種習慣。

  • ▪  所有參數應在同一行中,或者每個參數佔用一行且使用冒號對齊。如:

           [myObject doFooWith:arg1 name:arg2 error:arg3];
    

           [myObject doFooWith:arg1
                          name:arg2
    
                         error:arg3];
    
  • ▪  和方法的聲明一樣,如果無法使用冒號對齊時,每個參數一行、縮進4個字符、垂直對其(而非使用冒號對齊)。如:
    [myObj short:arg1

               longKeyword:arg2
    
               evenLongerKeyword:arg3];
    

    @public @private
    @public @private使用單獨一行,且縮進1個字符

Protocals

  • ▪  類型標示符、代理名稱、尖括號間不留空格。

  • ▪  該規則同樣適用於:類聲明、實例變量和方法聲明。如:

           @interface MyProtocoledClass : NSObject<NSWindowDelegate> {
            @private
    
             id<MyFancyDelegate> _delegate;
           }
    
           - (void)setDelegate:(id<MyFancyDelegate>)aDelegate;
    

    @end

  • ▪  如果類聲明中包含多個protocal,每個protocal佔用一行,縮進2個字符。如:@interface CustomViewController : ViewController<

             AbcDelegate,
    

    DefDelegate>{

    ...}

    命名
    類名

  • ▪  類名(及其category name protocal name)的首字母大寫,寫使用首字母大寫的形式分割單詞

  • ▪  在面向特定應用的代碼中,類名應儘量避免使用前綴,每個類都使用相同的前綴影響可讀性。

  • ▪  在面向多應用的代碼中,推薦使用前綴。如:GTMSendMessageCategory Name

    待完善方法名

  • ▪  方法名的首字母小寫,且使用首字母大寫的形式分割單詞。方法的參數使用相同的規則。

  • ▪  方法名+參數應儘量讀起來像一句話(如:)。在這裏查看蘋果對方法命名的規範

  • ▪  getter的方法名和變量名應相同。不允許使用“get”前綴。如:

    - (id) getDelegate; // 禁止

    - (id)delegate; // 對頭

  • ▪  本規則僅針對Objective-C代碼,C++代碼使用C++的習慣

    變量名

  • ▪  變量名應使用容易意會的應用全稱,且首字母小寫,且使用首字母大寫的形式分割單詞

  • ▪  成員變量使用“_”作爲前綴(如:“NSString *_varName;”。雖然這與蘋果的標準(使

    “_”作爲後綴)相沖突,但基於以下原因,仍使用“_”作爲前綴。
    使用“_”作爲前綴,更容易在有代碼自動補全功能的IDE中區分屬性

    (self.userInfo)”成員變量(_userInfo)”

  • ▪  常量(#define, enums, const等)使用小寫“k”作爲前綴,首字母大寫來分割單詞。如:

           kInvalidHandle
    

    註釋
    待完善

    • Cocoa Objective-C特有的規則

  • 成員變量使用@private。如:

        @interface MyClass : NSObject {
         @private
    
          id _myInstanceVariable;
        }
    
        // public accessors, setter takes ownership
        - (id)myInstanceVariable;
        - (void)setMyInstanceVariable:(id)theVar;
        @end
    
  • Indentify Designated Initializer待完善

  • Override Desingated Initializer

待完善初始化

在初始化方法中,不要將變量初始化爲“0”“nil”,那是多餘的

內存中所有的新創建的對象(isa除外)都是0,所以不需要重複初始化爲“0”“nil”避免顯式的調用+new方法

禁止直接調用NSObject的類方法+new,也不要在子類中重載它。使用allocinit方法保持公共API的簡潔性

待完善
#import VS #include

使用#import引入Ojbective-COjbective-C++頭文件,使用#include引入CC++頭文件

import根框架(root frameworks),而非各單個文件
雖然有時我們僅需要框架(如Cocoa Foundation)的某幾個頭文件,但引入根文件編譯

器會運行的更快。因爲根框架(root frameworks)一般會預編譯,所以加載會更快。再次強調:使用 #import 而非 #include 來引入Objective-C框架。如:
#import <Foundation/NSArray.h> // 禁止
#import <Foundation/NSString.h>

...

#import <Foundation/Foundation.h> // 對頭創建對象時儘量使用autorelease

  • ▪  創建臨時對象時,儘量同時在同一行中 autorelease 掉,而非使用單獨的 release 語句

  • ▪  雖然這樣會稍微有點慢,但這樣可以阻止因爲提前 return 或其他意外情況導致的內存泄露。

       通盤來看這是值得的。如:
    

    // 避免這樣使用(除非有性能的考慮)
    MyController* controller = [[MyController alloc] init];
    // ...
    這裏的代碼可能會提前return ...
    [controller release];
    // 這樣更好
    MyController* controller = [[[MyController alloc] init] autorelease];

    autorelease,再retain

  • ▪  在爲對象賦值時,遵從autorelease,再retain”

  • ▪  在將一個新創建的對象賦給變量時,要先將舊對象release掉,否則會內存泄露。市面上有很

    多方法來handle這種情況,這裏選擇autorelease,再retain”的方法,這種方法不易引入error。注意:在循環中這種方法會填滿”autorelease pool,稍稍影響效率,但是Google和我( :P )認爲這個代價是可以接受的。如:
    - (void)setFoo:(GMFoo *)aFoo {

    [foo_ autorelease]; // 如果foo_aFoo是同一個對象(foo_ == aFoo),dealloc不會被調用

          foo_ = [aFoo retain];
        }
    

    dealloc的順序要與變量聲明的順序相同
    這有利於review代碼
    如果dealloc中調用其他方法來release變量,將被release的變量以註釋的形式標註清楚

    NSString的屬性的setter使用copy

禁止使用retain,以防止意外的修改了NSString變量的值。如:

    - (void)setFoo:(NSString *)aFoo {
      [foo_ autorelease];
      foo_ = [aFoo copy];

}

    @property (nonatomic, copy) NSString *aString;

避免拋出異常(Throwing Exceptions)待完善

nil 的檢查
僅在有業務邏輯需求時檢查nil,而非爲了防止崩潰

nil 發送消息不會導致系統崩潰,Objective-C運行時負責處理。BOOL陷阱

  • ▪  int值轉換爲BOOL時應特別小心。避免直接和YES比較

  • ▪  Objective-C中,BOOL被定義爲unsigned char,這意味着除了 YES(1) NO(0)外它

    還可以是其他值。禁止將int直接轉換(cast or convert)爲BOOL

  • ▪  常見的錯誤包括:將數組的大小、指針值或位運算符的結果轉換(cast or convert)爲

    BOOL,因爲該BOOL值的結果取決於整型值的最後一位

  • ▪  將整型值轉換爲BOOL的方法:使用三元運算符返回YES / NO,或使用位運算符(&&,||,!)

  • ▪  BOOL_Boolbool之間的轉換是安全的,但是BOOLBoolean間的轉換不是安全的,所以

    Boolean看成整型值。

  • ▪  Objective-C中,只允許使用BOOL

  • ▪  如:

    // 禁止
    - (BOOL)isBold {

          return [self fontTraits] & NSFontBoldTrait;
        }
    
        - (BOOL)isValid {
          return [self stringValue];
    

    }

    // 對頭
    - (BOOL)isBold {

          return ([self fontTraits] & NSFontBoldTrait) ? YES : NO;
        }
    
        - (BOOL)isValid {
          return [self stringValue] != nil;
    
        }
        - (BOOL)isEnabled {
    
          return [self isValid] && [self isBold];
        }
    
  • ▪  禁止直接將BOOLYES/NO比較,如:// 禁止

        BOOL great = [foo isGreat];
        if (great == YES)
    

    ...

    // 對頭
    BOOL great = [foo isGreat];if (great)

    ...

    屬性

命名:與去掉“_”前綴的成員變量相同,使用@synthesize將二者聯繫起來。如:

    // abcd.h
    @interface MyClass : NSObject {
     @private
      NSString *_name;
    }
    @property (copy, nonatomic) NSString *name;
    @end
    // abcd.m
    @implementation MyClass
    @synthesize name = _name;
    @end

位置:屬性的聲明緊隨成員變量塊之後,中間空一行,無縮進。如上例所示嚴把權限:對不需要外部修改的屬性使用readonly
NSString使用copy而非retain
CFType使用@dynamic, 禁止使用@synthesize

除非必須,使用nonatomic• Cocoa Pattern

Delegate Pattern(委託)

  • ▪  delegate對象使用assign,禁止使用retain。因爲retain會導致循環索引導致內存泄露,

    並且此類型的內存泄露無法被Instrument發現,極難調試

  • ▪  成員變量命名爲_delegate,屬性名爲delegate

    Model/View/ControllerModelView分離

    不多解釋
    Controller獨立於ViewController

    不要在與view相關的類中添加過多的業務邏輯代碼,這讓代碼的可重用性很差

    Controller負責業務邏輯代碼,且Controller的代碼與view儘量無關
    使用@protocal 定義回調APIs,如果並非所有方法都是必須的,使用@optional標示

    其他
    init方法和dealloc方法是是最常用的方法,所以將他們放在類實現的開始位置使用空格將相同的變量、屬性對齊,使用換行分組 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章