iOS 代碼規(guī)范

基本原則:

清晰又簡潔的代碼當(dāng)然是最好,但簡潔不如清晰重要。不要使用單詞的簡寫,除了非常常用的簡寫以外,盡量使用單詞全稱。API的名稱不要有歧義,一看API就知道是以什么方式做了什么事情。

1、命名

類的命名:

大駝峰式命名:即每個單詞的首字母采用大些字母。
使用能夠反映類功能的名詞短語。

DoneCourseListView

分類(類別)命名:

與類命名相同,此外需添加要擴(kuò)展的類名和“+”

NSString+MTValidate

方法命名:

小駝峰式命名:首字母小寫,之后每個單詞首字母都大寫
方法名使用動詞短語。

- (void)setPostValue:(int)value

方法參數(shù)命名:

首字母小寫,之后每個單詞首字母都大寫
具有足夠的說明性,不需要添加類型前綴

- (void)sendUserInfo:(NSDictionary*)userInfo

宏命名:

全部大寫,單詞間用 _ 分隔。[不帶參數(shù)]

#define THIS_IS_AN_MACRO @"THIS_IS_AN_MACRO"

以字母 k 開頭,后面遵循大駝峰命名。[不帶參數(shù)]

#define kWidth self.frame.size.width

小駝峰命名。[帶參數(shù)]

#define getImageUrl(url) [NSURL URLWithString:[NSString stringWithFormat:@"%@%@",kBaseUrl,url]]

枚舉類型命名:

Enum類型的命名與類的命名規(guī)則一致
Enum中枚舉內(nèi)容的命名需要以該Enum類型名稱開頭
NS_ENUM定義通用枚舉,NS_OPTIONS定義位移枚舉

typedef NS_ENUM(NSInteger,UIViewAnimationTransition) {
      UIViewAnimationTransitionNone,
      UIViewAnimationTransitionFlipFromLeft,
      UIViewAnimationTransitionFlipFromRight,          
      UIViewAnimationTransitionCurlUp,
      UIViewAnimationTransitionCurlDown
};

typedef NS_OPTIONS(NSUInteger,UIControlState) {
      UIControlStateNormal=0,
      UIControlStateHighlighted=1<<0,
      UIControlStateDisabled=1<<1

};

分組命名:

使用英文,首字母大寫,之后每個單詞首字母都大寫
每個分組使用模塊的名字
使用的開源庫統(tǒng)一放在“Library”分組下
使用的公共組件統(tǒng)一放在“Common”分組下
視圖控制器及AppDelegate統(tǒng)一放在“Controllers”分組下

后綴要求:

視圖控制器的子類應(yīng)該以“ViewController”或者“Controller”做后綴

CourseViewController

試圖的子類應(yīng)該以“View”做后綴

CourseView

協(xié)議(委托)使用Delegate或者DataSource作為后綴

VideoPlayerDelegate

按鈕的子類應(yīng)添加后綴“Button”,UI控件以此類推

LoginButton

2、注釋

優(yōu)秀的代碼大部分是可以自描述的,我們完全可以用代碼本身來表達(dá)它到底在干什么,而不需要注釋的輔助,如果做不到命名盡量的見名知意的話,就可以適當(dāng)?shù)奶砑右恍┳⑨尰蛘適ark。

但是以下三種情況比較適合寫注釋:

1、公共接口(注釋要告訴閱讀代碼的人,當(dāng)前類能實(shí)現(xiàn)什么功能)。
2、涉及到比較深層專業(yè)知識的代碼(注釋要體現(xiàn)出實(shí)現(xiàn)原理和思想)。
3、容易產(chǎn)生歧義的代碼(但是嚴(yán)格來說,容易讓人產(chǎn)生歧義的代碼是不允許存在的)。

除了上述這三種情況,如果別人只能依靠注釋才能讀懂你的代碼的時候,就要反思代碼出現(xiàn)了什么問題。對于注釋的內(nèi)容,相對于“做了什么”,更應(yīng)該說明“為什么這么做”。

注釋示例:

1、屬性注釋

/// 學(xué)生
@property (nonatomic, strong) Student *student;

2、類注釋

/** 類信息。此注釋用在類聲明的開頭。
@TestClass
@這是一個測試類
*/
@interfaceTestClass :UIView

@end

3、方法命名注釋

/**
 根據(jù)請求的 URL 與 parameters 同步取出緩存數(shù)據(jù)
 @param  URL        請求的URL
 @param  parameters 請求的參數(shù)
 @return  緩存的服務(wù)器數(shù)據(jù)
*/
+ (id)httpCacheForURL:(NSString *)URL parameters:(id)parameters;

4、import注釋
如果有一個以上的import語句,就對這些語句進(jìn)行分組,每個分組的注釋是可選的。

// Frameworks
#import<Foundation/Foundation.h>;

// Models
#import "UserInfoModel.h"

// Views
#import "CourseCountView"
#import "MineHeaderView.h"

5、代碼塊注釋
單行的用//+空格開頭,多行的采用/* */注釋

//    [self.allCourseV dataWithTitle:@"購買課時" count:[NSString stringWithFormat:@"%lu", (unsigned long)allCount] desc:@""];

6、TODO
使用//TODO:說明 標(biāo)記一些未完成的或完成的不盡如人意的地方

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions

{
    //TODO:增加初始化
    return YES;
}

3、格式化代碼

1、 指針 "*" 位置

定義一個對象時,指針 "*" 靠近變量

 NSString *userName;

2、 方法的聲明和定義

在 - 、+ 和 返回值 之間留一個空格,方法名和第一個參數(shù)之間不留空格

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;

3、 代碼縮進(jìn)

  1. 使用 xcode 默認(rèn)縮進(jìn),即 tab = 4空格
  2. 使用 xcode 中 re-indent 功能定期對代碼格式進(jìn)行整理,步聚:點(diǎn)選要進(jìn)行重構(gòu)的文檔, Control+A 全選該文檔,然后選擇XCODE -> Editor -> Structure -> Re-Indent 即可對代碼進(jìn)行重構(gòu) !
  3. 相同類型變量聲明需要獨(dú)行聲明

4、對方法進(jìn)行分組

使用 #pragma mark -方式對類的方法進(jìn)行分組
方法與方法之間空一行

#pragma mark - private methods
- (**void**)samplePrivateMethod
 {...}

- (**void**)sampleForIf
 {...}

5、 大括號寫法

對于類的method: 左括號另起一行寫(遵循蘋果官方文檔)
對于其他使用場景(if,for,while,switch等): 左括號跟在第一行后邊

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

任何需要寫大括號的部分,不得省略

//錯誤示例
- (void)wrongExamples
{
    BOOL someCondition = YES;
    if (someCondition)
        NSLog(@"this is wrong!!!");
    while (someCondition)
        NSLog(@"this is wrong!!!");
}

4、編碼規(guī)范

1、if語句

①、須列出所有分支(窮舉所有的情況),而且每個分支都須給出明確的結(jié)果。

推薦

var hintStr;
if (count <3) {
    hintStr ="Good";
} else {
    hintStr ="";
}

不推薦

var hintStr;
if (count <3) {
    hintStr ="Good";
}

②、不要使用過多的分支,要善于使用return來提前返回錯誤的情況,把最正確的情況放到最后返回。

推薦

if (!user.UserName) return NO;
if (!user.Password) return NO;
if (!user.Email) return NO;
return YES;

不推薦

BOOL isValid = NO;
if (user.UserName)
{
    if (user.Password)
    {
        if (user.Email) isValid = YES;
    }
}
return isValid;

③、條件過多,過長的時候應(yīng)該換行(1)。條件表達(dá)式如果很長,則需要將他們提取出來賦給一個BOOL值(2),或者抽取出一個方法(3)
(1)

if(condition1 &&
    condition2 &&
    condition3 &&
    condition4) {
    // Do something
}

(2)

BOOL finalCondition = condition1 && condition2 && condition3 && condition4
if  (finalCondition) {
    // Do something
}

(3)

if ([self canDelete]){
    // Do something
}

- (BOOL)canDelete
{
    BOOL finalCondition1 = condition1 && condition2
    BOOL finalCondition2 =  condition3 && condition4
    return condition1 && condition2;
}

不推薦

if (condition1 && condition2 && condition3 && condition4) {
    // Do something
}

④、條件語句的判斷應(yīng)該是變量在右,常量在左。
if (object == nil)容易誤寫成賦值語句, if (!object)寫法很簡潔

推薦

if (6== count) {

}

if (nil == object) {

}

if (!object) {

}

不推薦

if(count == 6) {

}

if(object == nil) {

}

⑤、每個分支的實(shí)現(xiàn)代碼都須被大括號包圍
推薦:

if (!error) {
    return success;
}

也可以:

if (!error) return success;

不推薦

if (!error)
    return success;

2、for語句
①、不可在for循環(huán)內(nèi)修改循環(huán)變量,防止for循環(huán)失去控制。
②、避免使用continue和break。

  • continue和break所描述的是“什么時候不做什么”,所以為了讀懂二者所在的代碼,我們需要在頭腦里將他們?nèi)》础?/li>
  • 最好不要讓這兩個東西出現(xiàn),因?yàn)槲覀兊拇a只要體現(xiàn)出“什么時候做什么”就好了,而且通過適當(dāng)?shù)姆椒?,是可以將這兩個東西消滅掉的:
  • 如果出現(xiàn)了continue,只需要把continue的條件取反即可
var filteredProducts = Array()
for level in products {
    if level.hasPrefix("bad") {
        continue;
    }
    filteredProducts.append(level)
}

我們可以看到,通過判斷字符串里是否含有“bad”這個prefix來過濾掉一些值。其實(shí)我們是可以通過取反,來避免使用continue的:

for level in products {
    if !level.hasPrefix("bad") {
        filteredProducts.append(level)
    }
}

消除 while 里的 break:將 break 的條件取反,并合并到主循環(huán)里
在 while 里的 break 其實(shí)就相當(dāng)于“不存在”,既然是不存在的東西就完全可以在最開始的條件語句中將其排除。
while 里的 break:

while (condition1) {
    ...
    if (condition2) {
        break;
    }
}

取反并合并到主條件:

while (condition1 && !condition2) {
    ...
}

在有返回值的方法里消除break:將break轉(zhuǎn)換為return立即返回

//在有返回值的方法里break之后,再返回某個值。其實(shí)完全可以在break的那一行直接返回。
func hasBadProductIn(products: Array<String>) -> Bool {
    var result = false
    for level in products {
        if level.hasPrefix("bad") {
            result = true
            break
        }
    }
    return result
}
//這樣寫的話不用特意聲明一個變量來特意保存需要返回的值,看起來非常簡潔,可讀性高。
func hasBadProductIn(products: Array<String>) -> Bool {
    for level in products {
        if level.hasPrefix("bad") {
           return true
        }
    }
    return false
}

3、Switch語句

①、每個分支都必須用大括號括起來

switch (integer) {
    case 1: {
        // ...
       break;
    } 
    case 2: {
        // ...
        break;
    }
    default: {
        // ...
        break;
    }
}

②、使用枚舉類型時,不能有default分支, 除了使用枚舉類型以外,都必須有default分支,在Switch語句使用枚舉類型的時候,如果使用了default分支,在將來就無法通過編譯器來檢查新增的枚舉類型了。

RWTLeftMenuTopItemType menuType = RWTLeftMenuTopItemMain;
switch (menuType) {
    case RWTLeftMenuTopItemMain: {
        // ...
        break;
    }
    case RWTLeftMenuTopItemShows: {
        // ...
        break;
    }
    case RWTLeftMenuTopItemSchedule: {
        // ...
        break;
    }
}

4、函數(shù)

①、一個函數(shù)只做一件事(單一原則)
②、對于有返回值的函數(shù)(方法),每一個分支都必須有返回值
③、對輸入?yún)?shù)的正確性和有效性進(jìn)行檢查,參數(shù)錯誤立即返回
④、如果在不同的函數(shù)內(nèi)部有相同的功能,應(yīng)該把相同的功能抽取出來單獨(dú)作為另一個函數(shù)
⑤、將函數(shù)內(nèi)部比較復(fù)雜的邏輯提取出來作為單獨(dú)的函數(shù)

5、團(tuán)隊(duì)規(guī)范

說明:一個好的團(tuán)隊(duì),理所當(dāng)然有其嚴(yán)格的代碼規(guī)范,好的代碼不僅可以提高團(tuán)隊(duì)的開放效率,也更利于團(tuán)隊(duì)項(xiàng)目的后期維護(hù),統(tǒng)一的代碼風(fēng)格,也是團(tuán)隊(duì)的核心,所以規(guī)范代碼很有必要!

1、刪除多余的空行 所有方法與方法之間空1行 所有代碼塊之間空1行

2、刪除多余的注釋
刪除注釋掉的代碼
刪除沒有意義的注釋

3、刪除多余的方法
如果方法沒有使用到,請刪除它
如果方法沒有執(zhí)行任何業(yè)務(wù)邏輯,請刪除它或者給出一定注釋

4、刪除未被使用的資源文件

5、添加必要的注釋
所有.h 文件中的property 需要給出注釋
所有自定義的方法需要給出注釋
比較大的代碼塊需要給出注釋
所有代碼中出現(xiàn)的阿拉伯?dāng)?shù)字需要給出注釋
程序中出現(xiàn)加密/解密 邏輯的操作地方,需要給出注釋說明過程(無論是系統(tǒng)還是自定義)

6、整體代碼風(fēng)格需要統(tǒng)一
代碼后面的”{“ 不需要單獨(dú)占用一行
邏輯運(yùn)算符 與“|” 代碼之前空一格
“#pragmamark -” 與下面的代碼之前不要空行
遵循一般性的代碼規(guī)范

參考:

iOS團(tuán)隊(duì)編程規(guī)范

【iOS】命名規(guī)范

iOS開發(fā)代碼規(guī)范(通用)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、命名規(guī)范 1、統(tǒng)一要求含義清楚,盡量做到不需要注釋也能了解其作用,若做不到,就加注釋,使用全稱,不使用縮寫。 ...
    Untils閱讀 622評論 0 0
  • iOS編程規(guī)范0規(guī)范 0.1前言 為??高產(chǎn)品代碼質(zhì)量,指導(dǎo)廣大軟件開發(fā)人員編寫出簡潔、可維護(hù)、可靠、可 測試、高效...
    iOS行者閱讀 4,609評論 21 35
  • -------------------------------------編碼原則----------------...
    yanhooIT閱讀 1,078評論 0 11
  • 這里有些關(guān)于編碼風(fēng)格Apple官方文檔,如果有些東西沒有提及,可以在以下文檔來查找更多細(xì)節(jié): The Object...
    Loki9527閱讀 419評論 0 0
  • ——李茂英 窟野河畔寂樓臺 日落西山醉歸來 遠(yuǎn)道冬風(fēng)入我懷 老樹蕭蕭踏荒苔 附:欲脩其身者先正其心欲正其心...
    李茂英閱讀 299評論 1 11

友情鏈接更多精彩內(nèi)容