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)全部使用小寫字母逻谦,除下表中保留字外掌实,private
、protected
邦马、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)引用。