代碼規范

推薦文章:禪與 Objective-C 編程藝

前言


為??高產品代碼質量,指導廣大軟件開發人員編寫出簡潔、可維護、可靠、可測試、高效 、 可移植的代碼,編程規范修訂工作組分析 、總結了我司的各種典型編碼問題,并參考了業界編程規 范近年來的成果,重新對我司1999年版編程規范進行了梳理、優化、刷新,編寫了本規范。 本規范將分為完整版和精簡版,完整版將包括更多的樣例 、規范的解釋以及參考材料(what &why),而精簡版將只包含規則部分(what)以便查閱。在本規范的最后,列出了一些業界比較優秀的編程規范,作為延伸閱讀參考材料。

代碼總體原則


1、清晰第一清晰性是易于維護 、易于重構的程序必需具備的特征 。代碼首先是給人讀的,好的代碼應當可以像文章一樣發聲朗誦出來。目前軟件維護期成本占整個生命周期成本的40%~90%。根據業界經驗,維護期變更代碼的成本,小型系統是開發期的5倍,大型系統( 100萬行代碼以上)可以達到100倍。
業界的調查指出,開發組平均大約一半的人力用于彌補過去的錯誤,而不是添加新的功能來幫助公司??高競爭力。

“程序必須為閱讀它的人而編寫,只是順便用于機器執行。”——HaroldAbelson和Gerald Jay Sussman
“編寫程序應該以人為本,計算機第二。”——Steve McConnell

本規范通過后文中的原則(如頭優秀的代碼可以自我解釋,不通過注釋即可輕易讀懂/頭文 件中適合放置接口的聲明,不適合放置實現/除了常見的通用縮寫以外,不使用單詞縮寫,不得使 用漢語拼音)、規則(如防止局部變量與全局變量同名)等說明清晰的重要性。
一般情況下,代碼的可閱讀性高于性能,只有確定性能是瓶頸時,才應該主動優化。
2、簡潔為美簡潔就是易于理解并且易于實現。代碼越長越難以看懂,也就越容易在修改時引入錯誤 。寫 的代碼越多,意味著出錯的地方越多,也就意味著代碼的可靠性越低 。因此,我們??倡大家通過編 寫簡潔明了的代碼來??升代碼可靠性。
廢棄的代碼(沒有被調用的函數和全局變量)要及時清除,重復代碼應該盡可能??煉成函數 。
3、選擇合適的風格,與代碼原有風格保持一致產品所有人共同分享同一種風格所帶來的好處,遠遠超出為了統一而付出的
代價 。在公司已 有編碼規范的指導下,審慎地編排代碼以使代碼盡可能清晰,是一項非常重要的技能。如果重構/修改其他風格的代碼時,比較明智的做法是根據現有代碼的現有風格繼續編寫代碼 。

規范實施、解釋


本規范制定了編寫iOS程序的基本原則、規則和建議。本規范適用于公司內所有iOS軟件。本規范自發布之日起生效,對以后新編寫的和修改的代碼應遵守本規范。本規范由質量體系發布和維護。實施中遇到問題,可以 在組內出。 個體程序員不得違反本規范中的相關規則。

術語定義


頭文件

  • #import引用Objective-C/Objective-C++頭文件;#include引用C/C++頭文件;使用#include時要注意#define頭保護。

  • #import頭文件按模塊分類。
    說明:對頭文件按模塊分類,使代碼易讀,也便于理解。

  • #import的順序,應該是先引用自定義類,再引用系統類/框架。
    說明:將系統類放在最后引入,可避免和檢驗自定義類的頭文件引用不完整 漏洞。

  • #import根框架而不是單獨的零散文件
    說明:當你試圖從框架(如Cocoa或者Foundation)中包含若干零散的系統頭文件時,實際上包 含頂層根框架的話,編譯器要做的工作更少。根框架通常已經經過預編譯,加載更快。

  • @class與#import
    說明:如需要繼承類或執行協議,可以在.h中進行#import類或協議;其他情況下,在.h中聲明用@classs聲明此類即可。這樣可以減少因頭文件依賴引起重復編譯,??高編譯速度。

常量&變量

  • init和dealloc內避免使用訪問器
    說明:在init和dealloc方法執行的過程中,子類可能會處在一個不一致的狀態,所以這些方 法中的代碼應避免調用訪問器。子類尚未初始化,或在init和dealloc方法執行時已經被銷毀,會使訪問器方法很可能不可靠。 實際上,應在這些方法中直接對 內部成員變量進行賦值或釋放操作。

  • 禁止對屬性做出錯誤的內部成員變量聲明
    說明:xcode4.4開始會自動@synthesize ,為@ property聲明一個前綴下劃線的內部成員變量。因 此,不需要為屬性重復做出內部成員變量聲明。同時,禁止 對屬性做出錯誤的內部成員變量聲明 。

  • 使用常類型變量,而不是內嵌的字符串字面值或數字
    說明:常類型變量便于復用常用的變量值(如π),同時可以快速地修改值而無需查找替換。

  • 不用在init方法中,將成員變量初始化為0或者nil
    說明:剛分配的對象,默認值都是0,除了isa指針(譯者注: NSObject的isa識對象的類型)。所以不用在初始化器里面寫一堆將成員初始化為0或者nil的代碼。

  • 按實際需要來定義成員變量的作用域
    說明:
    1、如果只是單純的private變量,最好聲明在interface里。
    2、如果是類的public屬性,就用property寫在.h文件里。
    3、如果自己內部需要setter和getter來實現一些東西,就在.m文件的類目里用property來聲明。 不要將私有的實例變量和方法聲明在頭文件中,應將私有變量和方法聲明在實現文件的類擴展內 。

  • 字符串應使用copy屬性(Attribute)
    說明:應該用copy屬性(attribute)聲明NSString屬性(property)。 從邏輯上,確保遵守NSString的setter必須使用copy而不是retain的原則。

  • 謹慎聲明屬性的原子性
    說明:一定要注意屬性(property)的開銷。缺省情況下,所有synthesize的setter和getter都是原子的。這會給每個get或者set帶來一定的同步開銷。將屬性( property )聲明為nonatomic,除非你需要原子性。

  • 點引用只用于簡單的屬性set、get操作
    說明:點引用只用于簡單的屬性set、get操作,但不應該用它來調用對象的其它操作。

  • autorelease優先,retain其次(非ARC)
    說明:當給一個變量賦值新的對象時,必須先釋放掉舊的對象以避免內存泄露。有很多“正確的”方法可以處理這種情況。我們則選擇“autorelease之后retain”的方法,因為事實證明它不 容易出錯。注意大的循環會填滿autorelease池,并且可能效率上會差一點,但權衡之下我們認為是可以接受的。

  • 使用nil來檢查應用程序的邏輯流程,而不是避免崩潰
    說明:Objective-C運行時會處理向nil對象發送消息的情況。如果方法沒有返回值,就沒關系。 如果有返回值,可能由于運行時架構、返回值類型以及OS X版本的不同而不同,參見Apple’s documentation。注意,這和C/C++中檢查指針是否為’NULL’很不一樣,C/C++運行時不做任何檢查,從而導致 應用程序崩潰。因此你仍然需要保證你不會對一個C/C++的空指針解引用。

  • BOOL的陷阱,不要直接將BOOL值與YES進行比較
    說明:Ojbective-C中把BOOL定義成無符號字符型,這意味著BOOL類型的值遠不止YES(1)或NO(0),所以,不要直接將BOOL值與YES進行比較。

//示例-1:
BOOL a = 2.5;
if (a == YES) {
      NSLog(@"a == yes"); }
else if(a == NO) {
NSLog(@"a == no"); 
} else {
NSLog(@"a == other");
}
NSLog(@"a+0.5 = %f",a+0.5);
iOS編程規范v1.0
==========2014-04-07 21:56:14.280 2014-04-07 21:56:14.281 :test[1224:907] a == other test[1224:907] a+0.5 = 2.500000
//示例-2:
BOOL a =130;
if (a == YES) {
      NSLog(@"a == yes"); }
else if(a == NO) {
      NSLog(@"a == no"); 
} else {
      NSLog(@"a == other");
    }
NSLog(@"a=%hhd a+0.5 = %f",a,a+0.5);
==========2014-04-07 22:14:07.986:test[1510:907] a == other2014-04-07 22:14:07.988 test[1510:907] a=-126 a+0.5 =-125.500000
  • BOOL的陷阱,不要直接把整形轉換成BOOL
    說明:Ojbective-C中把BOOL定義成無符號字符型,不要直接把整形轉換成BOOL。常見的錯誤 包括將數組的大小、指針值及位運算的結果直接轉換成BOOL ,取決于整型結果的最后一個字節,很可能會產生一個NO值。當轉換整形至BOOL時,使用三目操作符來返回YES或者NO。(譯者 注:讀者可以試一下任意的256的整數的轉換結果,如256、512 ...)
    例:
//示例:錯誤的用法:
-(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];
 }
  • 盡量使用NSInteger,而不是int
    說明:當需要使用int類型的變量的時候,可以像寫C的程序一樣,用int,也可以用NSInteger,但 更推薦使用NSInteger,因為這樣就不用考慮設備是32位的還是64位的.

-點標記語法
說明:屬性和冪等方法(多次調用和一次調用返回的結果相同)使用點標記語法訪問,其他的情況 使用方括號標記語法。
示例:

//良好的風格:
view.backgroundColor = [UIColor orangeColor]; 
[UIApplication sharedApplication].delegate;

//不良的風格:
[view setBackgroundColor:[UIColor orangeColor]]; UIApplication.sharedApplication.delegate;

類和方法

  • 當子類需要使用init函數時,確保已經重載了父類的構造函數。
    說明:當子類需要使用init函數時,確保已經重載了父類的構造函數 。否則,子類的初始化不會調 用,這會導致很多很難定位的bug。

  • 出參與入參需對應
    說明:在32位系統中,int和long都是32位的,但是在64位系統中,long則是64位的。將long賦值給int,在64位系統中,會出現truncate的隱患。

  • 明確指定構造函數
    說明:對于需要繼承你的類的人來說,明確指定構造函數十分重要 。這樣他們就可以只重寫一個構 造函數(可能是幾個)來保證他們的子類的構造函數會被調用 。這也有助于將來別人調試你的類時,理解初始化代碼的工作流程。

  • 避免重載+new
    說明:不要調用NSObject的類方法new,或在子類中重載new方法。使用new方法會使關于內存分配 的代碼審核變得很困難。使用alloc和init來創建并初始化對象。

  • 保持公共API簡單
    說明:保持類簡單;避免“廚房水槽( kitchen-sink)”式的API。如果一個函數壓根沒必要公開,就不要這么做。用私有類別保證公共頭文件整潔。與C++不同, Objective-C沒有方法來區分公共的方法和私有的方法–所有的方法都是公共的(譯者注:這取決于Objective-C運行時的方法調用的消息機制)。因此,除非客戶端的代碼期望 使用某個方法,不要把這個方法放進公共API中。盡可能的避免了你不希望被調用的方法卻被調 用到。這包括重載父類的方法 。對于內部實現所需要的方法,在實現的文件中定義一個類別,而不 是把它們放進公有的頭文件中。

  • 大的@implementation用categories拆分成更容易理解的小塊。
    說明:便于理解的同時,還可以為最適合的類添加新的、特定應用程序的功能。
    例如,當添加一個“middle truncation”方法時,創建一個NSString的新類別并把方法放在里面,要比創建任意 的一個新類把方法放進里面好得多。

  • 用宏定義表達式時,要使用完備的括號。
    示例:
    如下定義的宏都存在一定的風險。
#define RECTANGLE_AREA( a, b ) a * b
#define RECTANGLE_AREA( a, b ) (a * b)
 #define RECTANGLE_AREA( a, b ) (a) * (b)

正確的定義應為:

#define RECTANGLE_AREA( a, b )  ((a) * (b))
  • 將宏所定義的多條表達式放在大括號中。
    示例:下面的語句只有宏的第一條表達式被執行。為了說明問題, for語句的書寫稍 不符規范。
#define INTI_RECT_VALUE( a, b )\a = 0;\b = 0;for (index = 0; index <
RECT_TOTAL_NUM; index++) INTI_RECT_VALUE( rect.a, rect.b );

正確的用法應為:

#define INTI_RECT_VALUE( a, b )\ {\a = 0;\b = 0;\}
  • 使用宏時,不允許參數發生變化。
    示例:
    如下用法可能導致錯誤。
#define SQUARE( a ) ((a) * (a))int a = 5;int b;b = SQUARE( a++ ); //結果:a = 7,即執行了兩次增1。 

正確的用法是:

b = SQUARE( a );a++; //結果:a = 6,即只執行了一次增1。

其他

  • 委托模式
    說明:
    委托對象不應該被retain實現委托模式的類應:
    1、擁有一個名為_delegate的實例變量來引用委托。
    2、因此,訪問器方法應該命名為delegate和setDelegate:。
    3、_delegate對象不應該被retain。

  • 模型/視圖/控制器(MVC)
    說明:分離模型與視圖。分離控制器與視圖、模型。
    1、分離模型與視圖:
    不要假設模型或者數據源的表示方法 。保持數據源與表示層之間的接口抽象。視圖不需要了解模型的邏輯(主要的規則是問問你自己,對于數據源的一個實例,有沒有可能有多種不同狀態的表示方法)。
    2、分離控制器與模型、視圖:
    不要把所有的“業務邏輯”放進跟視圖有關的類中。這使代碼非常難以復用 。使用控制器類來處理這些代碼,但保證控制器不需要了解太多表示層的 邏輯。

  • 應該使用線程安全的模式創建共享的單例實例
    示例:

+(instancetype)sharedInstance {
      static id sharedInstance = nil;
      static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{
      sharedInstance = [[self alloc] init];
       });
      return sharedInstance; 
}
  • 盡量使用不透明視圖
    說明:不透明的視圖可以極大地??高渲染的速度。因此如非必要,可以將table cell及其子視圖的opaque屬性設為YES(默認值)。

  • 做條件判斷時,應使用Golden Path模式
    說明:The goal here is to make the code on the left margin to be the “expected” code execution path and the code that is indented to be the exception. Consistency in this area is important to code readability.
    示例:

//良好的風格:
-(void)someMethod{
      if (![someOther boolValue])
             return;
       //Do something important 
}
//不良好的風格:
 -(void)someMethod{
      if ([someOther boolValue]) { 
            //Do something important
      }
}
================================
//良好的風格:
-(void)someMethod{
        if ([someOther boolValue]) { 
              //Do something important 
               return;
        }
        //Do something else important 
}
//不良好的風格:
-(void)someMethod{
          if ([someOther boolValue]) { 
                  //Do something important
          } else {
                  //Do something else important
          }
}
================================
//例外:
-(void)someMethod{
        if ([someOther boolValue]) {
              //Do something important
        } else {
                //Do something else important 
         }

        //Do this no matter what 
}
  • 異常和錯誤處理
    不要在流控制語句中使用異常( NSException )。異常僅用于表明程序員的錯誤。為了表明一個錯誤,使用NSError *。 當一個方法通過引用返回一個錯誤參數,應該檢測返回值的狀態,而不是錯誤參數的狀態。
//良好的風格:
NSError *error;
if (![self trySomethingWithError:&error]) {
     // Handle Error
}
//不良的風格:
NSError *error;
[self trySomethingWithError:&error]; 
if (error) {
       // Handle Error
}
//在方法執行成功的情況下賦值非Null值給錯誤參數,會使路徑跳轉到假條件分支(隨后程序奔潰)
  • 三元運算符
    說明:
    長的三元運算符應使用圓括號括起來。三元運算符僅用于賦值和做參數。Blah *a = (stuff == thing ? foo : bar);
    合并的nil三元運算符應該盡量避免。
    示例:
//不良的風格:
Blah *b = thingThatCouldBeNil ?: defaultValue;
//多分支條件應該使用if語句或重構為實例變量。
// 良好的風格:
result = a > b ? x : y;
///不良的風格:
result = a > b ? x = c > d ? c : d : y;

命名


  • 關于命名和命名風格
    說明:
    對于易維護的代碼而言,命名規則非常重要。Objective-C的方法名往往十分長,但代碼塊 讀起來就像散文一樣,不需要太多的代碼注釋。
    當編寫純粹的Objective-C代碼時,我們基本遵守標準的Objective-C namingrules,這 些命名規則可能與C++風格指南中的大相徑庭。例如, Google的C++風格指南中推薦使用下劃線分隔的單詞作為變量名,而(蘋果的)風格指南則使用駝峰命名法,這在Objective-C社區中非 常普遍。
    命名可適當使用縮略詞。但必須確保,這些縮略詞是久經歷史,認識性比較高的縮略詞。如 下:縮略詞。不要使用,你自己認為大家可能會理解的縮略詞 。因為,跳出語言環境之后,這個縮 略詞就變得難懂了。
    當編寫Objective-C++代碼時,事情就不這么簡單了。許多項目需要實現跨平臺的C++ API,并混合一些Objective-C、Cocoa代碼,或者直接以C++為后端,前端用本地Cocoa代碼。 這就導致了兩種命名方式直接不統一。我們的解決方案是:編碼風格取決于方法/函數以哪種語言 實現。如果在一個@implementation語句中,就使用Objective-C的風格。如果實現一個C++的類,就使用C++的風格。這樣避免了一個函數里面實例變量和局部變量命名規則混亂,嚴重影響 可讀性。

  • 命名盡量簡潔,但不能因為簡潔而使命名難以理解
    示例:

//Code
insertObject: atIndex: insert:at: removeObjectAtIndex: removeObject:remove:In general, don’t abbreviate names of things.
/***/
//Code
destinationSelection
destSel
setBackgroundColor:
setBkgdColor:

常量和變量

  • 關于變量名
    說明:
    變量名應該以小寫字母開頭,并使用駝峰格式 。盡量為變量起一個??述
    性的名字 。不要擔心 浪費列寬,因為讓新的代碼閱讀者立即理解你的代碼更重要。
    示例:
//錯誤的命名: 
int w;
int nerr;
int nCompConns;
tix = [[NSMutableArray alloc] init];
obj = [someObject object];
p = [network port];
//正確的命名:
 int numErrors;
int numCompletedConnections;
tickets = [[NSMutableArray alloc] init]; 
userInfo = [someObject object];
port = [network port];
  • 實例變量
    說明:
    實例變量應該混合大小寫,并以下劃線作為 前綴,如_usernameTextField
    然而,如果不 能使用Objective-C 2.0(操作系統版本的限制),并且使用了KVO/KVC綁定成員變量時,我們允 許例外(譯者注: KVO=Key Value
    Observing,KVC=Key Value Coding)。這種情況下,可以以一 個下劃線作為成員變量名字的前綴,這是蘋果所接受的鍵/值命名慣例。如果可以使用Objective-C 2.0,@property以及@synthesize??供了遵從這一命名規則的解決方案。

  • 常量
    常量名(如宏定義、枚舉、靜態局部變量等)應該以小寫字母k開頭,使用駝峰格式分隔單詞,
    示例:

kInvalidHandle
kWritePerm
  • 不要使用單個字符來定義變量名。
    說明:
    即時變量只是一個index,為它取名index,而不是i、j、k。 一般循環語句的當前對象的命名前綴包括“ one ”、“ a/an ”。對于簡單的單個對象使用“ item ”命名。
    示例:
//良好的風格:
for (i = 0; i < count; i++) {
      oneObject = [ allObjects objectAtIndex: i];
      NSLog (@"oneObject: %@", oneObject); 
}
NSEnumerator *e = [allObjects objectEnumerator];
id item;
while (item = [e nextObject])
      NSLog (@"item: %@", item);
  • 對于NSString、NSArray、NSNumber或BOOL類型,變量的命名一般不需要表明其 類型。
    示例:
//良好的風格:
NSString *accountName;
NSMutableArray *mailboxes;
NSArray *defaultHeaders;
BOOL userInputWasUpdated;
//不良的風格: 
NSString *accountNameString ; 
NSMutableArray  *mailbox Array ; 
NSArray *defaultHeaders Array ;
BOOL userInputWasUpdated BOOL ;
//如果變量不是以上基本常用類型,則變量的命名就應該反映出自身的類型 。但有時僅需要某 些類的一個實例的情況下,那么只需要基于類名進行命名。
NSImage *previewPaneImage ; 
NSProgressIndicator *uploadIndicator ;
NSFontManager * fontManager ; 
//基于類名命名
//大部分情況下, NSArray或NSSet類型的變量只需要使用單詞復數形式(比如mailboxes ),不必在命名中包含“ mutable ”。如果復數變量不是NSArray或NSSet類型,則 需要指定其類型。
//良好的風格:
NSDictionary * keyedAccountNames; 
NSDictionary * messageDictionary ; 
NSIndexSet * selectedMailboxesIndexSet ;

類和方法


  • 不要使用下劃線前綴來聲明私有方法。
    說明:蘋果保留這一風格。

  • 方法的每個參數必須有參數聲明,盡可能對參數做出??述,不能為空

示例:

//正確
-(void)sendAction:(SEL)aSelectortoObject:(id)anObject forAllCells:(BOOL)flag;
//錯誤
-(void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag;
//正確
- (id)viewWithTag:(NSInteger)aTag; 
//錯誤
 - (id)taggedView:(int)aTag;

關于類名

  • 類名(以及類別、協議名)應首字母大寫,并以駝峰格式分割單詞。應用層的代碼,應該盡 量避免不必要的前綴 。為每個類都添加相同的前綴無助于可讀性 。當編寫的代碼期望在不同應用程 序間復用時,應使用前綴(如:GTMSendMessage )。

  • 關于類別名
    說明:類別名應該有兩三個字母的前綴以表示類別是項目的一部分或者該類別是通用的 。類別名應 該包含它所擴展的類的名字。
    比如我們要基于NSString創建一個用于解析的類別,我們將把類別放在一個名為GTMNSString+Parsing.h的文件中。類別本身命名為GTMStringParsingAdditions (是的,我們 知道類別名和文件名不一樣,但是這個文件中可能存在多個不同的與解析有關類別)。類別中的方 法應該以gtm_myCategoryMethodOnAString:為前綴以避免命名沖突,因為Objective-C只有一 個名字空間 。如果代碼不會分享出去,也不會運行在不同的地址空間中,方法名字就不那么重要了 。類名與包含類別名的括號之間,應該以一個空格分隔。

  • 關于方法名
    說明:一個方法的命名首先??述返回什么,接著是什么情況下被返回 。方法前面中冒號的前面??述傳入參數的類型。 以下類方法和實例方法命名的格式語法:
    [object/class thing+ condition ];
    [object/class thing+ input :input];
    [object/class thing+identifer :input];
    方法名應該以小寫字母開頭,并混合駝峰格式。每個具名參數也應該以小寫字母開頭。 方法名應盡量讀起來就像句子,這表示你應該選擇與方法名連在一起讀起來通順的參數名。(例如,convertPoint:fromRect:或replaceCharactersInRange:withString:)。
    詳情參見Apple’s Guide to Naming Methods。訪問器方法應該與他們 要獲取的成員變量的名字一樣,但不應該以get作為前綴。
    例如:

-(id)getDelegate; // AVOID
-(id)delegate; // GOOD示例:
rate= [number floatValue];
newString= [string posedStringWithCanonicalMapping ]; 
subarray=[array arrayWithRange :segment];
decom = [path stringByExpandingTildeInPath ];
string = [string ByAppendingString :@"Extra Text"];
sub = [array objectAtIndex :3];
string = [NSString WithFormat :@"%f",1.5]; 
array = [NSArray WithObject :newString];
//不良的風格:
-sortInfo //是返回排序結果還是給info做排序-refreshTimer
 //返回一個用于刷新的定時器還是刷新定時器
-update
 //更新什么,如何更新
//良好的風格:
-currentSortInfo // "current"清楚地修飾了名詞SortInfo
-refreshDefaultTimer // refresh是一個動詞。-updateMenuItemTitle //一個正在發生的動作
這僅限于Objective-C的方法名。C++的方法與函數的命名規則應該遵從C++風格指南中 的規則。
  • 關于方法的參數名
    說明:
    方法參數名一般使用的前綴包括“ the ”、“ an ”、“ new ”。
    示例:
//良好的風格:
-(void)setTitle:(NSString*)aTitle;
//Cocoa命名舉例:
realPath
fullString
object
//類方法newStringnewArray良好的自定義方法命名風格:recipients = [emailrecipients SortedByLastName ];
newEmail = [CDCEmail emailWithSubjectLine :@"Extra Text"]; 
emails = [mailbox messagesReceivedAfterDate :yesterdayDate];
當需要獲取對象值的另一種類型的時候,方法命名的格式語法如下: [object adjective +thing];
[object adjective +thing+ condition ];
[object adjective +thing+input :input];
//良好的自定義方法命名風格:
capitalized = [name capitalized String];
-(void) setName:
-(id) keyForOption:
-(NSArray *) emailsForMailbox:
-(CDCEmail *) emailForRecipients: (NSArray *) theRecipients;
-(NSString *) newName; (CDCOption *) anOption (CDCMailbox *) theMailbox;
  • 方法的參數名不要使用“and”做鏈接。
    說明:當參數較多時,代碼會顯得冗余。有一個例外,當參數??述的是兩個不同的action時,可以 用“and”做鏈接。

  • 框架類模塊中,在類名和常類型變量名前添加一個由三個大寫的字母組成的前綴(如RNC )。
    說明:
    由于Objective-C不支持名字空間,為了防止出現命名空間的沖突,在類名和常類型變量 名前添加一個由三個大寫的字母組成的前綴(如RNC ),對于Core Data實體名則可以忽略此規 則。如果你子類化了標準的Cocoa類,將前綴和父類名合并是一個很好的做法。如繼承UITableView的類可命名為RNCTableView。

其他

關于文件名
說明:
文件名須反映出其實現了什么類–包括大小寫。遵循你所參與項目的約定。 文件的擴展名應該如下:
類別的文件名應該包含被擴展的類名,如: GTMNSString+Utils.h或GTMNSTextView+Autocomplete.h

  • 關于Objective-C++
    說明:源代碼文件內,Ojbective-C++代碼遵循你正在實現的函數/方法的風格。為了最小化Cocoa/Objective-C與C++之間命名風格的沖突,根據待實現的函數/方法選 擇編碼風格。實現@implementation語句塊時,使用Objective-C的命名規則;
    如果實現一個C++
    .h ===C/C++/Objective-C的頭文件
    .m ===Ojbective-C實現文件
    .mm ===Ojbective-C++的實現文件
    .cc ===純C++的實現文件
    .c ===純C的實現文件的類,就使用C++命名規則。

  • 圖片資源的命名
    說明:圖片的命名應該保持一致,以圖片的用途??述作為圖片文件名 。文件名的命名使用駝峰式大 小寫風格,文件名后可跟隨一個自定義的類名或者是自定義的屬性名(如果有屬性名)、也可以 再跟上顏色??述以及/或者位置、圖片的最終狀態。
    示例:

良好的風格:
RefreshBarButtonItem / RefreshBarButtonItem@2x和
RefreshBarButtonItemSelected / RefreshBarButtonItemSelected@2x
ArticleNavigationBarWhite / ArticleNavigationBarWhite@2x和ArticleNavigationBarBlackSelected / ArticleNavigationBarBlackSelected@2x.
被用作相似用途的圖片應該使用一個圖片文件夾進行分開管理。
  • 關于縮略詞1
    說明:
    雖然方法命名不應使用縮略詞,然而有些縮略詞在過去被反復的使用,所以使用這些縮略詞 能更好的的表達代碼的含義。
縮略詞 含義和備注
alloc 分配,撥出
alt 輪流,交替
app 應用程序。比如NSApp表示全局程序對象
calc 計算
dealloc 銷毀、析構
func 函數
horiz 水平的
info 信息
init 初始化
max 最大的
min 最小的
msg 消息
nib Interface Builder文檔
pboard 黏貼板(僅對常量)
rect 矩形
temp 臨時、暫時
vert 垂直的

以下是一些常用的首字母縮略詞ASCIIPDFXML:

HTML
URL
RTF
HTTP
TIFF
JPG
PNG
GIF
LZW
ROM
RGB
CMYK
MIDI
FTP

注釋


  • 文件/類/框架的注釋盡量完整。變量/方法的注釋盡量簡潔。
    說明:
    盡管注釋很重要,但最好的代碼應該自成文檔。 并且注釋的更新往往沒有代碼更新及時 。與 其寫一段復雜的注釋,不如直接起一個有意義的名字 。
    更新代碼時一定要更新注釋,防止對代碼造 成誤解。

  • 文件注釋
    說明:
    每個文件的開頭以文件內容的簡要??述起始,緊接著是作者,最后是版權聲明和 樣板。版權信息及作者每個文件應該按順序包括如下項:
    1、許可證
    2、文件內容的簡要??述
    3、代碼作者
    4、版權信息聲明(如:Copyright 2008 GoogleInc.)
    5、必要的話,加上許可證樣板。為項目選擇一個合適的授權樣板(例如,Apache 2.0, BSD, LGPL,GPL)。如果你對其他人的原始代碼作出重大的修改,請把你自己的名字添加到作者里面 。當另外一個代碼 貢獻者對文件有問題時,他需要知道怎么聯系你,這十分有用。

  • 使用javadoc-style注釋風格。
    說明:
    注釋的第一行是對注釋API的總結,隨后的注釋行是對代碼更多細節的解釋。
    示例:

良好的風格: 
/**
\* The maximum size of a download that is allowed.
\* If a response reports acontent length greater than the max  will be \* cancelled.
\*This is helpful for preventing excessive memory usage.
\* Setting this to zero will allow all downloads regardless of size. 
\* @default 150000 bytes
**/
@property (nonatomic) NSUInteger maxContentLength;
  • 聲明部分的注釋
    說明:
    每個接口、類別以及協議應輔以注釋,以??述它的目的及與整個項目的關系。如果你已經在文件頭部詳細??述了接口,可以直接說明“完整的??述請參見文件頭部”,但是一定 要有這部分注釋。 另外,公共接口的每個方法,都應該有注釋來解釋它的作用、參數、返回值以及其它影響。 如果有的話,為類的線程安全性作注釋。如果類的實例可以被多個線程訪問,記得注釋多線程條件下的使用規則。
// A delegate for NSApplication to handle notifications about app // launch and
shutdown. Owned by the main app controller. @interface MyAppDelegate :
NSObject {
...
} 
@end
  • 實現部分的注釋

說明:使用|來引用注釋中的變量名及符號名而不是使用引號。 這會避免二

義性,尤其是當符號是一個常用詞匯,這使用語句讀起來很糟糕。 示例:

對于符號count :// Sometimes we need |count| to be less than zero.或者當引用

已經包含引號的符號:// Remember to call |StringWithoutSpaces("foo bar baz")|

  • 程序中變量、方法命名盡量能以字面意思表示功能,對于需要用注釋來解釋的部分代碼,注釋以如下格式表述:
    示例:/**
    方法或變量說明 @param參數1說明(針對方法)* @param參數2說明(針對方法)* @return若方法有返回值則對返回值作說明*/

  • 每一個方法之前都有一個99字符寬的注釋行,注釋行相對于使用空行更能??高代碼的 辨識度,當一行代碼很長的時候,注釋行也起到了越界檢測的作用。
    注釋行: ///////////////////////////////////////////////////////////////////////////////////// //////////////

格式


  • 盡量讓你的代碼保持在100列之內。
    說明:我們深知Objective-C是一門繁冗的語言,在某些情況下略超100列可能有助于??高可讀 性,但這也只能是特例而已,不能成為開脫 。對于超長的代碼,我們要懷疑代碼邏輯的簡練性。 設置方法: Xcode > Preferences > Text
    Editing > Show page guide。
    空格

-指針變量的星號指示符應該緊靠變量。
示例:
NSString *text,而不是NSString* textNSString * text

-方法聲明中,-/ +和返回類型之間須使用一個空格。
示例:

-(void)doSomethingWithString:(NSString *)theString { ... }
  • 運算符間距1
    說明:
    二元運算符和參數之間需要放置一個空格,一元運算符、強制類型轉換和參數之間不放置空 格。關鍵字之后圓括號之前,需要放置一個空格。示例:
void *ptr = &value + 10 * 3; NewType a = (NewType) b;for ( int i = 0; i < 10; i ++ ) { doCoolThings();
}
  • 運算符間距2
    說明:
    數組和字典類型的字面值的 方括號兩邊 各放置一個空格。
NSArray *theShit = @[ @1 , @2, @3 ] ;

字典字面值的鍵和冒號之間沒有空格,冒號和值之間有一個空格。

NSDictionary *keyedShit = @{ GHDidCreateStyleGuide: @YES };

C函數聲明中,左括號的前面 不保留空格,并且函數名應該像類一樣帶有命名空間標識。
良好的風格:

void RNCwesomeFunctio n( BOOL hasSomeArgs);

長的字面值應被拆分為多行。
良好的風格:

NSArray *theShit = @[
@"Got some long string objects in here.", [AndSomeModelObjects too],@"Moar strings."];
NSDictionary *keyedShit = @{@"this.key": @"corresponds to this value",
@"otherKey": @"remoteData.payload", @"some": @"more",@"JSON":
@"keys",@"and": @"stuff",
};
  • 只使用空格,不使用制表符。一次縮進兩個空格。
    說明:
    我們使用空格縮進,不在代碼中使用制表符。在跨平臺開發中,不同IDE的tab對應縮進格式 不同。應該將編輯器設置成自動將制表符替換成空格。

  • 類型標識符和尖括號內的協議名之間,不能有任何空格。
    這條建議適用于類聲明、實例變量以及方法聲明。
    示例:

@interface MyProtocoledClass : NSObject { 
@private
id delegate_; 
}
-(void)setDelegate:(id)aDelegate; 
@end
  • @public和@private訪問修飾符應該以一個空格縮進。

示例:

@interface MyClass : NSObject {
@public ...
@private ...
} 
@end
  • 異常捕獲中,每個@標簽應該有獨立的一行,在@與{}之間需要有一個
    空格,@catch與被 捕捉到的異常對象的聲明之間也要有一個空格。
    如果你決定使用Objective-C的異常,那么就按下面的格式。不過你最好先看看 避免拋出異常 了 解下為什么不要使用異常。
@try {
      foo(); 
}
@catch (NSException *ex) { 
       bar(ex);
}@finally {
      baz(); 
}
  • 重載NSObject的方法
    如果重載了NSObject類的方法,強烈建議把它們放在@implementation內的起始處,這也是常 見的操作方法。通常適用(但不局限)于init..., copyWithZone:,以及dealloc方法。所有init...方法應 該放在一起, copyWithZone:緊隨其后,最后才是dealloc方法。

  • Delegates和protocol對象聲明在ivar的后面。
    說明:delegates的命名往往比較長。

  • 屬性聲明和定義的位置
    說明:
    屬性的聲明必須緊靠著類接口中的實例變量語句塊。屬性的定義必須在@implementation的 類定義的最上方。他們的縮進與包含他們的@interface以及@implementation語句一樣。
    示例:

@interface MyClass : NSObject { 
@private
NSString *name_; 
}
@property(copy, nonatomic) NSString *name; @end@implementation MyClass @synthesize name = name_;
- (id)init { ...}
@end
  • 當需要實現多個協議的時候,將每一個協議名拆分到單獨的行。
    示例:良好的風格:
@interface CustomModelViewController : TTViewController <
TTModelDelegate,TTURLRequestDelegate>
  • 關于方法參數與調用
    說明:
    方法有非常多的參數,應將每個參數單獨拆成一行,且每個參數前的冒號對齊。
    示例:
-(void)doSomethingWith:(GTMFoo *)theFoo 
                    rect:(NSRect)theRect
                interval:(float)theInterval {
... }

說明:當第一個關鍵字比其它的短時,保證下一行至少有 直對齊,而不是使用冒號對齊

  • 關于塊(閉包)
    說明:
    塊(block)適合用在target/selector模式下創建回調方法時,因為它使代碼更易讀。塊 中的代碼應該縮進4個空格。取決于塊的長度,下列都是合理的
    風格準則:
    1、如果一行可以寫完塊,則沒必要換行。
    2、如果不得不換行,關括號應與塊聲明的第一個字符對齊。
    3、塊內的代碼須按4空格縮進。
    4、如果塊太長,比如超過20行,建議把它定義成一個局部變量,然后再使用該變量
    5、 如果塊不帶參數,^{之間無須空格。如果帶有參數, ^(之間無須空格,但) {之間須有一個
    空格。
    6、塊內允許按兩個空格縮進,但前??是和項目的其它代碼保持一致的縮進風格。

  • 左右花括號
    說明:
    方法簽名以及其他關鍵字( if/else/switch/wh ile等)后面跟隨的左花括號總是和語句出 現于同一行,而右花括號獨占一行。
    示例:
    良好的風格:

if (user.isHappy) {
       //Do something
}else {
       //Do something else
}

如果一個方法內有多個功能區域,可以使用空行分隔功能區域。

  • 條件體內的邏輯塊,需用花括號包圍
    說明:
    即使條件體只需編寫一行代碼也必須使用花括號。
    良好的風格做法:
if(!error) {
      return success;
 }
//不良的風格:
 if (!error)
      return success;
//或:
if (!error) return success;
  • 內部成員變量按邏輯分組.
    說明:便于理解這個類。

聲明


內容來自這

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,345評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,494評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,283評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,953評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,714評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,410評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,940評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,776評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,210評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,654評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容

  • iOS編程規范0規范 0.1前言 為??高產品代碼質量,指導廣大軟件開發人員編寫出簡潔、可維護、可靠、可 測試、高效...
    iOS行者閱讀 4,474評論 21 35
  • 示例 下面是一個示例頭文件,演示了@interface聲明的正確注釋和間隔 一個示例源文件,演示了一個接口的@ i...
    我是Damo閱讀 2,021評論 2 5
  • [TOC] 前言 這份文檔是Google Java編程風格規范的完整定義。當且僅當一個Java源文件符合此文檔中的...
    marine8888閱讀 1,954評論 0 1
  • 代碼格式 使用空格而不是制表符 Tab 不要在工程里使用 Tab 鍵,使用空格來進行縮進。在 Xcode > Pr...
    small_Sun閱讀 1,372評論 1 3
  • 在子組件定義了一個output事件,例如 @Output()myTestOutput: EventEmitter ...
    廈門第一帥哥閱讀 984評論 0 0