iOS 代碼規(guī)范

基本原則:

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

1、命名

類的命名:

大駝峰式命名:即每個(gè)單詞的首字母采用大些字母梳玫。
使用能夠反映類功能的名詞短語(yǔ)爹梁。

DoneCourseListView

分類(類別)命名:

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

NSString+MTValidate

方法命名:

小駝峰式命名:首字母小寫提澎,之后每個(gè)單詞首字母都大寫
方法名使用動(dòng)詞短語(yǔ)姚垃。

- (void)setPostValue:(int)value

方法參數(shù)命名:

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

- (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

};

分組命名:

使用英文绍昂,首字母大寫,之后每個(gè)單詞首字母都大寫
每個(gè)分組使用模塊的名字
使用的開源庫(kù)統(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è)知識(shí)的代碼(注釋要體現(xiàn)出實(shí)現(xiàn)原理和思想)亮靴。
3、容易產(chǎn)生歧義的代碼(但是嚴(yán)格來說于置,容易讓人產(chǎn)生歧義的代碼是不允許存在的)茧吊。

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

注釋示例:

1、屬性注釋

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

2尿孔、類注釋

/** 類信息俊柔。此注釋用在類聲明的開頭。
@TestClass
@這是一個(gè)測(cè)試類
*/
@interfaceTestClass :UIView

@end

3活合、方法命名注釋

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

4雏婶、import注釋
如果有一個(gè)以上的import語(yǔ)句,就對(duì)這些語(yǔ)句進(jìn)行分組白指,每個(gè)分組的注釋是可選的留晚。

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

// Models
#import "UserInfoModel.h"

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

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

//    [self.allCourseV dataWithTitle:@"購(gòu)買課時(shí)" 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橄唬、 指針 "*" 位置

定義一個(gè)對(duì)象時(shí)赋焕,指針 "*" 靠近變量

 NSString *userName;

2、 方法的聲明和定義

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

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

3犬庇、 代碼縮進(jìn)

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

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

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

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

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

5欢峰、 大括號(hào)寫法

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

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

任何需要寫大括號(hào)的部分,不得省略

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

4涨共、編碼規(guī)范

1纽帖、if語(yǔ)句

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

推薦

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

不推薦

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

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

推薦

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;

③、條件過多,過長(zhǎng)的時(shí)候應(yīng)該換行(1)褒傅。條件表達(dá)式如果很長(zhǎng)捷绒,則需要將他們提取出來賦給一個(gè)BOOL值(2),或者抽取出一個(gè)方法(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ǔ)句的判斷應(yīng)該是變量在右支鸡,常量在左。
if (object == nil)容易誤寫成賦值語(yǔ)句, if (!object)寫法很簡(jiǎn)潔

推薦

if (6== count) {

}

if (nil == object) {

}

if (!object) {

}

不推薦

if(count == 6) {

}

if(object == nil) {

}

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

if (!error) {
    return success;
}

也可以:

if (!error) return success;

不推薦

if (!error)
    return success;

2牧挣、for語(yǔ)句
①、不可在for循環(huán)內(nèi)修改循環(huán)變量醒陆,防止for循環(huán)失去控制瀑构。
②、避免使用continue和break刨摩。

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

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

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

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

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

取反并合并到主條件:

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

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

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

3暖璧、Switch語(yǔ)句

①、每個(gè)分支都必須用大括號(hào)括起來

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

②君旦、使用枚舉類型時(shí)澎办,不能有default分支, 除了使用枚舉類型以外金砍,都必須有default分支局蚀,在Switch語(yǔ)句使用枚舉類型的時(shí)候,如果使用了default分支恕稠,在將來就無法通過編譯器來檢查新增的枚舉類型了琅绅。

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

4、函數(shù)

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

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

說明:一個(gè)好的團(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、刪除多余的方法
如果方法沒有使用到堕阔,請(qǐng)刪除它
如果方法沒有執(zhí)行任何業(yè)務(wù)邏輯棍厂,請(qǐng)刪除它或者給出一定注釋

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)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末时呀,一起剝皮案震驚了整個(gè)濱河市张漂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谨娜,老刑警劉巖航攒,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異趴梢,居然都是意外死亡漠畜,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門坞靶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盆驹,“玉大人,你說我怎么就攤上這事滩愁。” “怎么了辫封?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵硝枉,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我倦微,道長(zhǎng)妻味,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任欣福,我火速辦了婚禮责球,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拓劝。我一直安慰自己雏逾,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布郑临。 她就那樣靜靜地躺著栖博,像睡著了一般。 火紅的嫁衣襯著肌膚如雪厢洞。 梳的紋絲不亂的頭發(fā)上仇让,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天典奉,我揣著相機(jī)與錄音,去河邊找鬼丧叽。 笑死卫玖,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的踊淳。 我是一名探鬼主播假瞬,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼嚣崭!你這毒婦竟也來了笨触?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤雹舀,失蹤者是張志新(化名)和其女友劉穎芦劣,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體说榆,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡虚吟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了签财。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片串慰。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖唱蒸,靈堂內(nèi)的尸體忽然破棺而出邦鲫,到底是詐尸還是另有隱情,我是刑警寧澤神汹,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布庆捺,位于F島的核電站,受9級(jí)特大地震影響屁魏,放射性物質(zhì)發(fā)生泄漏滔以。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一氓拼、第九天 我趴在偏房一處隱蔽的房頂上張望你画。 院中可真熱鬧,春花似錦桃漾、人聲如沸坏匪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)剥槐。三九已至,卻和暖如春宪摧,著一層夾襖步出監(jiān)牢的瞬間粒竖,已是汗流浹背颅崩。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蕊苗,地道東北人沿后。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像朽砰,于是被迫代替她去往敵國(guó)和親尖滚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

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

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