iOS 代碼規(guī)范 團隊代碼規(guī)范 代碼總結(jié)

iOS代碼規(guī)范總結(jié)

一些原則

  1. 長的,描述性的方法和變量命名是好的葵姥。不要使用簡寫,除非是一些大家都知道的場景比如 VIP句携。如 bgView榔幸、reqURL、videoBtn矮嫉,修改為 backgroundView削咆、videoButton
  2. 方法名長沒問題,但含義清楚蠢笋,做好不加注釋代碼自我表述能力強拨齐。(前提是代碼足夠規(guī)范) 如下方wkWebView官方api:
- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL API_AVAILABLE(macos(10.11), ios(9.0));
  1. 不要過分追求技巧,降低代碼可讀性昨寞。
  2. 刪除沒必要的代碼瞻惋,可通過git等追溯找回,沒必要保留援岩。
  3. 在方法內(nèi)部不要重復(fù)計算某個值歼狼,適當(dāng)?shù)那闆r下可以將計算結(jié)果緩存起來。
  4. 減少單例的使用享怀。
  5. 提供一個統(tǒng)一的數(shù)據(jù)管理入口羽峰,不管是 MVC、MVVM凹蜈、MVP 模塊內(nèi)提供一個統(tǒng)一的數(shù)據(jù)管理入口會使得代碼變得更容易管理和維護限寞。
  6. 空行、空格的合理使用如下方代碼:
// 類仰坦、協(xié)議等之間模塊間空行履植,同類不空行
NS_ASSUME_NONNULL_BEGIN

@class WKBackForwardList;
@class WKBackForwardListItem;
@class WKNavigation;
@class WKSnapshotConfiguration;
@class WKWebViewConfiguration;

@protocol WKNavigationDelegate;
@protocol WKUIDelegate;

// 屬性間空行,屬性的各個修飾詞之間空格
/*! @abstract A copy of the configuration with which the web view was
 initialized. */
@property (nonatomic, readonly, copy) WKWebViewConfiguration *configuration;

/*! @abstract The web view's navigation delegate. */
@property (nullable, nonatomic, weak) id <WKNavigationDelegate> navigationDelegate;

/*! @abstract The web view's user interface delegate. */
@property (nullable, nonatomic, weak) id <WKUIDelegate> UIDelegate;

/*! @abstract The web view's back-forward list. */
@property (nonatomic, readonly, strong) WKBackForwardList *backForwardList;

// 方法間空行
- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER;

- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

/*! @abstract Navigates to a requested URL.
 @param request The request specifying the URL to which to navigate.
 @result A new navigation for the given request.
 */
- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;

// 方法實現(xiàn)名與實現(xiàn)體之間悄晃,空格
- (void)viewDidLoad {
    
    ///    
}

  1. 延后原則玫霎。
    • 頭文件能在.m中引入就不要在.h中引入,可以使用前向聲明妈橄。
    • 能用臨時變量就不要用成員變量庶近,能用成員變量就不要用屬性,能在.m中去做聲明就不要在.h中去做聲明眷蚓。
    • 盡可能少的在.h中暴露方法鼻种。

變量

  1. 一個變量最好只有一個作用,切勿為了節(jié)省代碼行數(shù)沙热,覺得一個變量可以做多個用途叉钥。(單一原則)
  2. 方法內(nèi)部如果有局部變量,那么局部變量應(yīng)該靠近在使用的地方篙贸,而不是全部在頂部聲明全部的局部變量投队。

運算符

  1. 1元運算符和變量之間不需要空格。例如:++n
  2. 2元運算符與變量之間需要空格隔開爵川。例如: containerWidth = 0.3 * Screen_Width
  3. 當(dāng)有多個運算符的時候需要使用括號來明確正確的順序敷鸦,可讀性較好。例如: 2 << (1 + 2 * 3 - 4)

條件表達式

  1. 當(dāng)有條件過多寝贡、過長的時候需要換行扒披,為了代碼看起來整齊些
//good
if (condition1() && 
    condition2() && 
    condition3() && 
    condition4()) {
  // Do something
}
//bad
if (condition1() && condition2() && condition3() && condition4()) { // Do something }
  1. 在一個代碼塊里面有個可能的情況時善于使用 return 來結(jié)束異常的情況。
- (void)doHomework {
    if (self.hungry) {
        return;
    }
    if (self.thirsty) {
        return;
    }
    if (self.tired) {
        return;
    }
    papapa.then.over;
}
  1. 每個分支的實現(xiàn)都必須使用 {} 包含兔甘。
// bad
if (self.hungry) self.eat() 
// good
if (self.hungry) {
    self.eat()
}
  1. 條件判斷的時候應(yīng)該是變量在左谎碍,條件在右。 if ( currentCursor == 2 ) { //... }
  2. switch 語句后面的每個分支都需要用大括號括起來洞焙。
  3. switch 語句后面的 default 分支必須存在蟆淀,除非是在對枚舉進行 switch。
switch (menuType) {  
  case menuTypeLeft: {
    // ...  
    break; 
   }
  case menuTypeRight: {
    // ...  
    break; 
  }
  case menuTypeTop: {
    // ...  
    break; 
  }
  case menuTypeBottom: {
    // ...  
    break; 
  }
}

類名

  1. 大寫駝峰式命名澡匪。每個單詞首字母大寫熔任。比如「申請記錄控制器」ApplyRecordsViewController
  2. 每個類型的命名以該類型結(jié)尾。
    • ViewController:使用 ViewController 結(jié)尾唁情。例子:ApplyRecordsViewController
    • View:使用 View 結(jié)尾疑苔。例子:分界線:boundaryView
    • NSArray:使用 s 結(jié)尾。比如商品分類數(shù)據(jù)源甸鸟。categories
    • UITableViewCell:使用 Cell 結(jié)尾惦费。比如 MyProfileCell
    • Protocol:使用 Delegate 或者 Datasource 結(jié)尾兵迅。比如 XQScanViewDelegate
    • Tool:工具類
    • 代理類:Delegate
    • Service 類:Service

類的注釋

有時候我們需要為我們創(chuàng)建的類設(shè)置一些注釋。我們可以在類的下面添加薪贫。

枚舉

枚舉的命名和類的命名相近恍箭。

typedef NS_ENUM(NSInteger, UIControlContentVerticalAlignment) {
    UIControlContentVerticalAlignmentCenter  = 0,
    UIControlContentVerticalAlignmentTop     = 1,
    UIControlContentVerticalAlignmentBottom  = 2,
    UIControlContentVerticalAlignmentFill    = 3,
};

  1. 全部大寫,單詞與單詞之間用 _ 連接瞧省。
  2. k 開頭扯夭。后面遵循大寫駝峰命名“柏遥「不帶參數(shù)」
#define HOME_PAGE_DID_SCROLL @"com.xq.home.page.tableview.did.scroll"
#define kHomePageDidScroll @"com.xq.home.page.tableview.did.scroll"

屬性

書寫規(guī)則交洗,基本上就是 @property 之后空一格,括號橡淑,里面的 線程修飾詞构拳、內(nèi)存修飾詞、讀寫修飾詞梁棠,空一格 類 對象名稱
根據(jù)不同的場景選擇合適的修飾符隐圾。

@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, assign, readonly) BOOL loading;   
@property (nonatomic, weak) id<#delegate#> delegate;
@property (nonatomic, copy) <#returnType#> (^<#Block#>)(<#parType#>);

單例

單例適合全局管理狀態(tài)或者事件的場景。一旦創(chuàng)建掰茶,對象的指針保存在靜態(tài)區(qū)暇藏,單例對象在堆內(nèi)存中分配的內(nèi)存空間只有程序銷毀的時候才會釋放”艚基于這種特點盐碱,那么我們類似 UIApplication 對象,需要全局訪問唯一一個對象的情況才適合單例沪伙,或者訪問頻次較高的情況瓮顽。我們的功能模塊的生命周期肯定小于 App 的生命周期,如果多個單例對象的話围橡,勢必 App 的開銷會很大暖混,糟糕的情況系統(tǒng)會殺死 App。如果覺得非要用單例比較好翁授,那么注意需要在合適的場合 tearDown 掉拣播。

單例的使用場景概括如下:

  • 控制資源的使用,通過線程同步來控制資源的并發(fā)訪問收擦。
  • 控制實例的產(chǎn)生贮配,以達到節(jié)約資源的目的。
  • 控制數(shù)據(jù)的共享塞赂,在不建立直接關(guān)聯(lián)的條件下泪勒,讓多個不相關(guān)的進程或線程之間實現(xiàn)通信。
+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //because has rewrited allocWithZone  use NULL avoid endless loop lol.
        _sharedInstance = [[super allocWithZone:NULL] init];
    });
    
    return _sharedInstance;
}

+ (id)allocWithZone:(struct _NSZone *)zone {
    return [TestNSObject sharedInstance];
}

+ (instancetype)alloc {
    return [TestNSObject sharedInstance];
}

- (id)copy {
    return self;
}

- (id)mutableCopy {
    return self;
}

- (id)copyWithZone:(struct _NSZone *)zone {
    return self;
}

私有變量

推薦以 _ 開頭,寫在 .m 文件中圆存。例如 NSString * _somePrivateVariable

代理方法

  1. 類的實例必須作為方法的參數(shù)之一叼旋。
  2. 對于一些連續(xù)的狀態(tài)的,可以加一些 will(將要)沦辙、did(已經(jīng))
  3. 以類的名稱開頭
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;

- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;

方法

  1. 方法與方法之間間隔一行
  2. 大量的方法盡量要以組的形式放在一起送淆,比如生命周期函數(shù)、公有方法怕轿、私有方法、setter && getter辟拷、代理方法..
  3. 方法最后面的括號需要另起一行撞羽。遵循 Apple 的規(guī)范
  4. 對于其他場景的括號,括號不需要單獨換行衫冻。比如 if 后面的括號诀紊。
  5. 如果方法參數(shù)過多過長,建議多行書寫隅俘。用冒號進行對齊邻奠。
  6. 一個方法內(nèi)的代碼最好保持在50行以內(nèi),一般經(jīng)驗來看如果一個方法里面的代碼行數(shù)過多为居,代碼的閱讀體驗就很差(別問為什么碌宴,做過重構(gòu)代碼行數(shù)很長的人都有類似的心情)
  7. 一個函數(shù)只做一個事情,做到單一原則蒙畴。所有的類贰镣、方法設(shè)計好后就可以類似搭積木一樣實現(xiàn)一個系統(tǒng)。
  8. 對于有返回值的函數(shù)膳凝,且函數(shù)內(nèi)有分支情況碑隆。確保每個分支都有返回值。
  9. 函數(shù)如果有多個參數(shù)蹬音,外部傳入的參數(shù)需要檢驗參數(shù)的非空上煤、數(shù)據(jù)類型的合法性,參數(shù)錯誤做一些措施:立即返回著淆、斷言劫狠。
  10. 多個函數(shù)如果有邏輯重復(fù)的代碼,建議將重復(fù)的部分抽取出來永部,成為獨立的函數(shù)進行調(diào)用
- (instancetype)init {
    self = [super init];
    if (self) {
        <#statements#>
    }
    return self;
}

- (void)doHomework:(NSString *)name
            period:(NSInteger)second
            score:(NSInteger)score;
  1. 方法如果有多個參數(shù)的情況下需要注意是否需要介詞和連詞嘉熊。很多時候在不知道如何抉擇測時候思考下蘋果的一些 API 的方法命名。
//good
- (instancetype)initWithAge:(NSInteger)age name:(NSString *)name;

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;


//bad
- (instancetype)initWithAge:(NSInteger)age andName:(NSString *)name;

- (void)tableView:(UITableView *)tableView :(NSIndexPath *)indexPath;
  1. .m 文件中的私有方法需要在頂部進行聲明
  2. 方法組之間也有個順序問題扬舒。
  • 在文件最頂部實現(xiàn)屬性的聲明阐肤、私有方法的聲明(很多人省去這一步,問題不大,但是蠻多第三方的庫都寫了孕惜,看起來還是會很方便愧薛,建議書寫)。
  • 在生命周期的方法里面衫画,比如 viewDidLoad 里面只做界面的添加毫炉,而不是做界面的初始化,所有的 view 初始化建議放在 getter 里面去做削罩。往往 view 的初始化的代碼長度會比較長瞄勾、且一般會有多個 view 所以 getter 和 setter 一般建議放在最下面,這樣子頂部就可以很清楚的看到代碼的主要邏輯弥激。
  • 所有button进陡、gestureRecognizer 的響應(yīng)事件都放在這個區(qū)域里面,不要到處亂放微服。

文件基本上就是

//___FILEHEADER___

#import "___FILEBASENAME___.h"
/*ViewController*/

/*View&&Util*/

/*model*/

/*NetWork InterFace*/

/*Vender*/

@interface ___FILEBASENAMEASIDENTIFIER___ ()

@end

@implementation ___FILEBASENAMEASIDENTIFIER___


#pragma mark - life cycle
- (void)viewWillAppear:(BOOL)animated {
    [super viewDidAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = <#value#>;
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewDidAppear:animated];
    
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidAppear:animated];
    
}

#ifdef DEBUG
- (void)dealloc {
    NSLog(@"%s",__func__);
}
#endif

#pragma mark - public Method

#pragma mark - private method

#pragma mark - event response



#pragma mark - UITableViewDelegate

#pragma mark - UITableViewDataSource
//...(多個代理方法依次往下寫)

#pragma mark - getters and setters

@end

圖片資源

  1. 單個文件的命名
    文件資源的命名也需要一定的規(guī)范趾疚,形式為:功能模塊名類別功能_狀態(tài)@nx.png
    Setting_Button_search_selected@2x.png、Setting_Button_search_selected@3x.png
    Setting_Button_search_unselected@2x.png以蕴、Setting_Button_search_unselected@3x.png
  2. 資源的文件夾命名
    最好也參考 App 按照功能模塊建立對應(yīng)的實體文件夾目錄糙麦,最后到對應(yīng)的目錄下添加相應(yīng)的資源文件。

注釋

  1. 對于類的注釋寫在當(dāng)前類文件的頂部
  2. 對于屬性的注釋需要寫在屬性后面的地方丛肮。 //**/
  3. 對于 .h 文件中方法的注釋赡磅,一律按快捷鍵 command+option+/。三個快捷鍵解決宝与。按需在旁邊對方法進行說明解釋仆邓、返回值、參數(shù)的說明和解釋
  4. 對于 .m 文件中的方法的注釋伴鳖,在方法的旁邊添加 //节值。
  5. 注釋符和注釋內(nèi)容需要間隔一個空格。 例如: // fetch goods list

版本規(guī)范

采用 A.B.C 三位數(shù)字命名榜聂,比如:1.0.2搞疗,當(dāng)有更新的情況下按照下面的依據(jù)

版本號 右說明對齊標(biāo)題 示例
A.b.c 屬于重大內(nèi)容的更新 1.0.2 -> 2.0.0
a.B.c 屬于小部分內(nèi)容的更新 1.0.2 -> 1.1.1
a.b.C 屬于補丁更新 1.0.2 -> 1.0.3
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市须肆,隨后出現(xiàn)的幾起案子匿乃,更是在濱河造成了極大的恐慌,老刑警劉巖豌汇,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幢炸,死亡現(xiàn)場離奇詭異,居然都是意外死亡拒贱,警方通過查閱死者的電腦和手機宛徊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門佛嬉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人闸天,你說我怎么就攤上這事暖呕。” “怎么了苞氮?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵湾揽,是天一觀的道長。 經(jīng)常有香客問我笼吟,道長库物,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任贷帮,我火速辦了婚禮戚揭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘皿桑。我一直安慰自己,他們只是感情好蔬啡,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布诲侮。 她就那樣靜靜地躺著,像睡著了一般箱蟆。 火紅的嫁衣襯著肌膚如雪沟绪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天空猜,我揣著相機與錄音绽慈,去河邊找鬼。 笑死辈毯,一個胖子當(dāng)著我的面吹牛坝疼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谆沃,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼钝凶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了唁影?” 一聲冷哼從身側(cè)響起耕陷,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎据沈,沒想到半個月后哟沫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡锌介,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年嗜诀,在試婚紗的時候發(fā)現(xiàn)自己被綠了猾警。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡裹虫,死狀恐怖肿嘲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情筑公,我是刑警寧澤雳窟,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站匣屡,受9級特大地震影響封救,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜捣作,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一誉结、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧券躁,春花似錦惩坑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至慢哈,卻和暖如春蔓钟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背卵贱。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工滥沫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人键俱。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓兰绣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親编振。 傳聞我的和親對象是個殘疾皇子狭魂,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344