iOS 代碼規(guī)范文檔

iOS 代碼規(guī)范文檔

[toc]

修訂

序號 版本 修訂人 修訂日期 備注
1 1.0 李俊杰 2018-07-31 起草
2

概述

  • 制定目的:制定iOS 編碼規(guī)范绷旗,主要是為了規(guī)范公司內(nèi)部的iOS 代碼,提高代碼可讀性,降低溝通成本和學(xué)習(xí)成本。
  • 必然性:隨著iOS團(tuán)隊(duì)的人員數(shù)量不斷增多忿危,必須有一個(gè)規(guī)范來約束開發(fā)者,避免代碼格式百花齊放導(dǎo)致項(xiàng)目維護(hù)没龙、交接成本增加铺厨;同時(shí)室谚,在多人開發(fā)項(xiàng)目中減少溝通成本抱究,提升編碼效率嘉抓。
  • 適用對象:iOS 開發(fā)人員鳞疲, iOS 團(tuán)隊(duì)管理人員痊项。
  • 適用范圍:適用公司所有用Objective-C語言開發(fā)的iOS項(xiàng)目初婆。

文件及目錄管理規(guī)范

  • 項(xiàng)目創(chuàng)建完成開始編碼時(shí)殖蚕,必須遵從項(xiàng)目文件路徑和物理文件路徑對應(yīng)锐膜;

    例如:xcode目錄中存在Class目錄溪王,在硬盤的物理文件中必須存在Class文件夾腮鞍;xcode中Class目中的文件必須放到硬盤物理文件Class目錄中;

    • 每個(gè)項(xiàng)目有一個(gè)公用目錄放公共資源莹菱,根據(jù)具體的需求移国,在公共資源文件夾下,建立對應(yīng)的子類文件夾道伟。

    • 文件夾命名首字母必須大寫桥狡,遵循駝峰拼寫規(guī)則。em. Resources, ViewModels

    • 圖片資源

      • 圖片資源必須使用icon_開頭裹芝,由英文字母部逮、數(shù)字、“”組成嫂易。如果使用單詞必須使用完整單詞不允許使用簡寫兄朋;單詞之間使用“”區(qū)分。em. icon_head怜械,icon_feature_settings, icon_animation_ball1

      • 項(xiàng)目中沒有特殊原因的話颅和,所有圖片必須放到:Images.xcassets中,Images中根據(jù)項(xiàng)目模塊區(qū)分不同的目錄缕允,圖片名稱前加模塊名稱做為前綴峡扩,避免圖片沖突。

      • 不允許所有圖片都放到Images的根目錄下障本。

代碼注釋規(guī)范

  • 注釋可以采用’ /* / ’和’ // ’兩種注釋符號教届,涉及到多行注釋時(shí),盡量使用 ’ / */ ’驾霜。

  • 對于一行代碼的注釋可放在前一行及本行上案训,不允許放在下一行,更不允許在一行語句的中間加入注釋粪糙。

  • 單元文件的文件頭注釋說明應(yīng)按如下格式:

 ```   
//
//  AppDelegate.m //文件名
//  UniXin // 項(xiàng)目名
//
//  Created by JunJie on 2018/7/31. //創(chuàng)建人及日期
//  Copyright ? 2018年 Longfor Properties Co. Ltd. All rights reserved. //版權(quán)
//


 - 方法前面的注釋遵循以下格式:如果某項(xiàng)沒有强霎,不顯示。公共接口的每個(gè)方法蓉冈,都應(yīng)該有注釋來解釋它的作用城舞、參數(shù)、返回值以及其它影響(建議放到description中)寞酿。
 
  ``` 
   /**
  @description 根據(jù)輪子和車架創(chuàng)建一個(gè)汽車
  @param 輪子
  @param 車架
  @return 一個(gè)汽車
  */
  
  - (Car *)createCar:(NSString *)wheel carFrame:(NSString *)carFrame;
  ```
 
 - 使用 | 來引用注釋中的變量名及符號名而不是使用引號家夺。這會(huì)避免二義性,尤其是當(dāng)符號是一個(gè)常用詞匯熟嫩,這使用語句讀起來很糟糕秦踪。例如褐捻,對于符號 count :
例如:
// Sometimes we need |count| to be less than zero.(有時(shí)候我們需要|數(shù)量|的值小于0)

 - 不必每行都加注釋掸茅,在關(guān)鍵代碼處,5行代碼左右處做注釋柠逞;

 - 協(xié)議及模塊之間需要加#pragma marks - 來區(qū)分

## 編碼排版格式規(guī)范

### 空行

#### .h文件中的空行
- 文件說明與頭文件包涵(#import)之間空1行

//
//  ViewController.h
//  UniXin
//
//  Created by JunJie on 2018/7/31.
//  Copyright ? 2018年 Longfor Properties Co. Ltd. All rights reserved.
//

#import <UIKit/UIKit.h>
  ```
  • 頭文件包涵(#import)之間昧狮,如果需要分類區(qū)別,各類別之間空1行

      #import <AFNetworking.h>
      #import <UIKit+AFNetworking.h>
          
      #import <MJRefresh.h>
    
  • 頭文件包涵(#import)與@class之間空1行

    #import <MJRefresh.h>
    
    @class CenterViewController;
    
  • {} 外空1行板壮,書寫屬性逗鸣,如果需要分類區(qū)別,各類別之間空1行

  • 空1行開始寫方法,如果需要分類區(qū)別撒璧,各類別之間空1行

  • 方法完成后透葛,空1行 @end

#import <UIKit/UIkit.h>
#import <Foundation/Foundation.h>

#import "GODOtherClass.h"
#import "GODOtherModel.h"

@class GODAnotherClass;
@protocol GODAnotherProtocol;

@interface GODExample : NSObject {

    NSString *instanceVariable;
}

@propety (nonatomic, strong) GODOtherModel *otherModel;

- (void)test;

@end

.m中的空行

  • 文件說明與頭文件包涵( #import )之間空1行
  • 頭文件包涵( #import )之間,如果需要分類區(qū)別卿樱,各類別之間空1行
  • @implementation@synthesize 之間空一行僚害,@synthesize 不要使用逗號( )如果需要分類區(qū)別繁调,各類別之間空1行
  • @synthesize 與方法之間空1行
  • 各方法之間空1行
  • 方法名后空1行開始寫實(shí)現(xiàn)萨蚕。
  • 變量聲明后空1行。如果分類區(qū)別蹄胰,各類別之間空1行岳遥。
  • 條件,循環(huán)裕寨,選擇語句浩蓉,整個(gè)語句結(jié)束需要空1行。
  • 最后一個(gè)結(jié)束括號之前不空行帮坚。
  • 注釋與代碼之間不空行妻往。
  • #pragma mark -與方法之間空1行。
#pragma mark - private methods

- (void)privateMethod1 {

  NSString *innerVariable1 = nil;
  NSInteger innerVariable2 = 100;

  BOOL condition = YES;

  if (condition) {
      NSLog(@"xxxxx");
  }

  //do real logic
}

關(guān)于空格

  • .h中成員聲明時(shí)试和,類型與變量之間有至少1個(gè)空格讯泣。星號( )靠近變量,不靠近類型阅悍。(部分習(xí)慣好渠,所有變量可以以 對齊,中間留空)保留
  • @property 后有1個(gè)空格节视,() 里面拳锚,逗號后有1個(gè)空格,括號外寻行,先留1個(gè)空格霍掺,再聲明屬性
  • 方法+,-后拌蜘,與() 之間有1個(gè)空格
  • 返回類型與 之間有1個(gè)空格杆烁,方法參數(shù)中返回類型與 之間有1個(gè)空格
  • 多參數(shù)的方法,每一個(gè)參數(shù)后面都有1個(gè)空格
  • 將編輯器設(shè)置為1個(gè) TAB = 4個(gè)字符縮進(jìn)简卧,每次縮進(jìn)4個(gè)空格(系統(tǒng)默認(rèn)的)
  • 使用 Block 時(shí)兔魂,內(nèi)容四個(gè)空格縮進(jìn),^ 后帶有參數(shù)時(shí)举娩,參數(shù)與 { 之間有一個(gè)空格縮進(jìn)
  • @public@private 訪問修飾符應(yīng)該以一個(gè)空格縮進(jìn)析校。
  • 異常部分构罗,每個(gè) @ 標(biāo)簽應(yīng)該有獨(dú)立的一行,在 @{} 之間需要有一個(gè)空格智玻, @catch 與被捕捉到的異常對象的聲明之間也要有一個(gè)空格遂唧。 for 循環(huán)語句和 { 也有一個(gè)空格。

關(guān)于BOOL值

  • 不要用 if(obj==nil){} 吊奢,而用if(!obj){}
  • 比較時(shí)把常量放前面可以避免錯(cuò)誤蠢箩,不要用if(aIntValue==255){} ,而用if(255==aIntValue){} 事甜,避免漏掉一個(gè) 谬泌,而變成賦值
  • 不要用if(aBool==YES){} ,直接用 if(aBool){}
  • 聲明BOOL 類型屬性的時(shí)候要以 is 開頭,并且重寫getter

命名規(guī)范

保留字

Objective-c語言的保留字或關(guān)鍵詞應(yīng)全部使用小寫字母逻谦,除下表中保留字外掌实,privateprotected 邦马、public 贱鼻、在類型說明中也作為保留字使用。還有nonatomanic ,retain ,readwrite , readonly 等也有特殊的使用場合滋将。下表中的關(guān)鍵字不允許作為變量名使用邻悬。

_Bool _Complex _Imaginary auto break bycopy
return self short` restrict typeof union
void volatile while property public private
byref case char const continue default
do double const enum extern float
for got if in inline inout
int long oneway else out registre
static struct super switch signed sizeof

文件

  • 文件夾命名首字母必須大寫,遵循駝峰拼寫規(guī)則随闽。em. Resources, ViewModels

方法

  • 方法的名稱應(yīng)全部使用有意義的單詞組成父丰,且以小寫字母開頭,多單詞組合時(shí)掘宪,后面的單詞首字母大寫(駝峰式書寫)蛾扇。 同時(shí)盡量讓方法的命名讀起來像一句話,能夠傳達(dá)出方法的意思魏滚。em. userName

  • 設(shè)置類變量的內(nèi)容的方法應(yīng)使用set 作為前綴镀首,讀取變量的內(nèi)容的方法不應(yīng)使用get作為前綴。一般使用get 作為前綴鼠次,是需要改變傳入引用的值更哄。

    //錯(cuò)誤方式
    - (NSString *)getUsername;
    //正確方式
    - (NSString *)username;
    - (void)getWidth:(CGFloat *)width fromSize:(CGSzie)viewSize;
    
  • 方法中的參數(shù):第一個(gè)參數(shù)名稱要從函數(shù)名稱上攜帶出來,第二個(gè)參數(shù)的首字母小寫腥寇,多個(gè)單詞組合時(shí)成翩,后面單詞首字母大寫。參數(shù)有別名時(shí),參數(shù)別名與前一參數(shù)保留1個(gè)空格花颗。

    - (instancetype)initWithUserName:(NSString *) cardId:(NSString *)cardId; 
    
  • 方法名稱在同一類型操作的時(shí)候不要使用多個(gè)連續(xù)的介詞(wtih捕传、and)在多個(gè)參數(shù)之間連接惠拭。如果表示兩個(gè)相對獨(dú)立的操作扩劝,可以使用相關(guān)介詞連接庸论。

      //錯(cuò)誤
      - (instancetype)initWithName:(NSString *)name 
                  withPassword:(NSString *)password;
      //正確
      - (instancetype)initWithName:(NSString *)name 
                      password:(NSString *)password;
      
      //錯(cuò)誤,不要使用"and"來闡明有多個(gè)參數(shù) 
      - (instancetype)initWithName:(CGFloat)width andAge:(CGFloat)height;
      
      //正確棒呛,使用"and"來表示兩個(gè)相對獨(dú)立的操作 
      - (BOOL)openFile:(NSString )fullPath withApplication:(NSString )appName andDeactivate:(BOOL)flag;
    

變量

  • 變量必須起有意義的名字聂示,使其他組員可以很容易讀懂變量所代表的意義,變量命名可以采用同義的英文命名簇秒,可使用幾個(gè)英文單詞鱼喉,第一個(gè)單詞首字母小寫,其他單詞首字母大寫趋观。

    //錯(cuò)誤的命名   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];
    
  • 對于一些特殊類型的變量扛禽,命名時(shí)要帶上類型,如NSArray 的變量命名為xxxArray皱坛,其他的如xxxDictionary编曼,xxxSize等。這樣就可以從名稱上知道是什么類型的變量剩辟。千萬不能將NSArray的變量命名為xxxDictionary掐场。

  • 對于要和interface builder關(guān)聯(lián)的的輸出口變量,命名時(shí)要后綴以特定的控件名贩猎。

      UILabel *userNameLabel; 
      UIView  *backgroundView; 
    
  • 本規(guī)則僅針對Objective-C代碼熊户,C++/C代碼使用C++/C對應(yīng)的習(xí)慣;

  • 盡量避免使用全局變量吭服,如果必須使用全局變量則必須加前綴 ‘static_’,同時(shí)應(yīng)在變量名稱中體現(xiàn)變量的類型嚷堡。em. static_int_unreadNum,_static_NSString_appKey

  • 私有實(shí)例變量前加一個(gè)下劃線,如_dbPath艇棕。

  • 枚舉變量也要有相應(yīng)的前綴來區(qū)分不同的enum 變量麦到。比如官方的一個(gè)enum

typedef enum CGPathDrawingMode CGPathDrawingMode;     
/* Drawing modes for text. */     
enum CGTextDrawingMode  { 
     kCGTextFill,
     kCGTextStroke, 
     kCGTextFillStroke, 
     kCGTextInvisible, 
     kCGTextFillClip, 
     kCGTextStrokeClip, 
     kCGTextFillStrokeClip, 
     kCGTextClip 
}; 

常量

  • 避免在程序中直接出現(xiàn)常數(shù)欠肾,使用超過一次的應(yīng)以宏定義的形式來替代瓶颠。

  • 常數(shù)的宏定義應(yīng)與它實(shí)際使用時(shí)的類型相一致。如以3.0來定義浮點(diǎn)類型刺桃,用3表示整型粹淋。

  • 常量的命名應(yīng)當(dāng)能夠表達(dá)出它的用途,常量名(如宏定義瑟慈、枚舉桃移、靜態(tài)局部變量等)應(yīng)該以小寫字母 k 開頭,使用駝峰格式分隔單詞葛碧,如:

    FOUNDATION_EXTERN MSString * const kGODExampleDidFinishedNotification;
    extern NSString * const kGODLoginDidFinishedNotification;
    

static NSString *kGODCustomerCellID = @"GODCustomerCellID";

define kGODCustomerCellHeight 200.f

-  一些常量前加特殊前綴借杰,可以作為不同常量的區(qū)分

UserDefaultsKey 的變量前加UDKEY_,    
NotificationNameKey 前面加NNKEY_,    
DictionaryKey 前面加DICTKEY_, 
### 屬性

- 修飾符的順序:nonatomic > strong/weak/retain/copy > readonly > getter/setter=
- NSString類型的屬性使用copy進(jìn)行修飾。
- Block類型的屬性使用copy進(jìn)行修飾进泼。
- delegate類型的屬性使用weak進(jìn)行修飾蔗衡,系統(tǒng)會(huì)在dealloc的時(shí)候自動(dòng)設(shè)置成nil纤虽。以避免循環(huán)引用。
- 盡量避免使用原子性修飾绞惦,否則會(huì)因?yàn)橥讲僮鳟a(chǎn)生額外的開銷逼纸。默認(rèn)的設(shè)置是原子的。 

### 類

- 所有的類名济蝉,協(xié)議名(Protocol)均以大寫字母開頭杰刽,多單詞組合時(shí),后面的單詞首字母大寫王滤。類贺嫂、協(xié)議名必須是有意義的。
- 繼承自UIView的類以View結(jié)尾雁乡。em. UserInformationView
- 繼承自ViewController的類以viewController結(jié)尾涝婉。em. LoginViewController
- 所有保存數(shù)據(jù)的實(shí)體以Model結(jié)尾。em. userModel
- 分類(類別)命名:與類命名相同蔗怠,此外需添加要擴(kuò)展的類名和 `+`墩弯。 em. NSString+URLEncoding
- 協(xié)議(委托)命名:與類命名相同,此外需添加`protocol`后綴寞射。 em. UINavigationControllerProtocol

@protocol GODExampleProtocol <NSObject>

  @required
  - (NSInteger)numberOfTableViewIndexPath:(NSIndexPath *)indexPath;
  
  @optional
  - (void)didSelectedIndexPath:(NSIndexPath *)indexPath;

@end



### 其他
- 每個(gè)方法不能超過100行渔工,超過100行的代碼必須拆分。
- 嵌套語句不能超過3層桥温;超過3層必須優(yōu)化和拆分引矩。
- 每個(gè)類文件行數(shù)建議在500行左右,不能超過1000行侵浸,超過1000行必須考慮抽象類來重構(gòu)代碼旺韭。
- 代碼行度最大為100列(C++的是80),可以在xcode的Text Editing中修改掏觉。
- 盡可能保證 .h文件的簡潔性区端,可以不公開的API就不要公開了,寫在實(shí)現(xiàn)文件中即可澳腹。
- 及時(shí)刪除無用的注釋和無用的代碼织盼。
- 代碼中不應(yīng)該出現(xiàn)控件的絕對坐標(biāo),應(yīng)盡可能使用相對坐標(biāo)酱塔。
- 寫`delegate` 的時(shí)候類型應(yīng)該為`weak` 弱引用沥邻,以避免循環(huán)引用。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末羊娃,一起剝皮案震驚了整個(gè)濱河市唐全,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蕊玷,老刑警劉巖邮利,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弥雹,死亡現(xiàn)場離奇詭異,居然都是意外死亡近弟,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進(jìn)店門挺智,熙熙樓的掌柜王于貴愁眉苦臉地迎上來祷愉,“玉大人,你說我怎么就攤上這事赦颇《” “怎么了?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵媒怯,是天一觀的道長订讼。 經(jīng)常有香客問我,道長扇苞,這世上最難降的妖魔是什么欺殿? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮鳖敷,結(jié)果婚禮上脖苏,老公的妹妹穿的比我還像新娘。我一直安慰自己定踱,他們只是感情好棍潘,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著崖媚,像睡著了一般亦歉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上畅哑,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天肴楷,我揣著相機(jī)與錄音,去河邊找鬼荠呐。 笑死阶祭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的直秆。 我是一名探鬼主播濒募,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼圾结!你這毒婦竟也來了瑰剃?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤筝野,失蹤者是張志新(化名)和其女友劉穎晌姚,沒想到半個(gè)月后粤剧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡挥唠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年抵恋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宝磨。...
    茶點(diǎn)故事閱讀 40,427評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡弧关,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出唤锉,到底是詐尸還是另有隱情世囊,我是刑警寧澤,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布窿祥,位于F島的核電站株憾,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏晒衩。R本人自食惡果不足惜嗤瞎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望听系。 院中可真熱鬧猫胁,春花似錦、人聲如沸跛锌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽髓帽。三九已至菠赚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間郑藏,已是汗流浹背衡查。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留必盖,地道東北人拌牲。 一個(gè)月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像歌粥,于是被迫代替她去往敵國和親塌忽。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容

  • iOS編程規(guī)范0規(guī)范 0.1前言 為??高產(chǎn)品代碼質(zhì)量,指導(dǎo)廣大軟件開發(fā)人員編寫出簡潔失驶、可維護(hù)土居、可靠、可 測試、高效...
    iOS行者閱讀 4,464評論 21 35
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,109評論 1 32
  • 推薦文章:禪與 Objective-C 編程藝 前言 為??高產(chǎn)品代碼質(zhì)量,指導(dǎo)廣大軟件開發(fā)人員編寫出簡潔擦耀、可維護(hù)棉圈、...
    WolfTin閱讀 2,766評論 0 1
  • 代碼格式 使用空格而不是制表符 Tab 不要在工程里使用 Tab 鍵,使用空格來進(jìn)行縮進(jìn)眷蜓。在 Xcode > Pr...
    small_Sun閱讀 1,362評論 1 3
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 29,405評論 8 265