iOS 代碼規(guī)范文檔

朗境科技 移動團隊 郎鏡通代碼規(guī)范指南

介紹

關于這個編程語言的所有規(guī)范刷晋,如果這里沒有寫到人断,那就在蘋果的文檔里:

目錄

點語法

應該 始終 使用點語法來訪問或者修改屬性薛躬,訪問其他實例時首選括號壶熏。

推薦:

view.backgroundColor = UIColor.orangeColor;
UIApplication.sharedApplication.delegate;

反對:

[view setBackgroundColor:[UIColor orangeColor]];
[UIApplication sharedApplication].delegate;

間距

  • 一個縮進使用 4 個空格,永遠不要使用制表符(tab)縮進。請確保在 Xcode 中設置了此偏好。
  • 方法的大括號和其他的大括號(if/else/switch/while 等等)始終和聲明在同一行開始,在新的一行結(jié)束喻杈。

推薦:

if (user.isHappy) {
    // Do something
}
else {
    // Do something else
}
  • 方法之間應該正好空一行,這有助于視覺清晰度和代碼組織性狰晚。在方法中的功能塊之間應該使用空白分開,但往往可能應該創(chuàng)建一個新的方法缴啡。
  • @synthesize@dynamic 在實現(xiàn)中每個都應該占一個新行壁晒。

條件判斷

條件判斷主體部分應該始終使用大括號括住來防止出錯,即使它可以不用大括號(例如它只需要一行)业栅。這些錯誤包括添加第二行(代碼)并希望它是 if 語句的一部分時秒咐。還有另外一種更危險的,當 if 語句里面的一行被注釋掉碘裕,下一行就會在不經(jīng)意間成為了這個 if 語句的一部分携取。此外,這種風格也更符合所有其他的條件判斷帮孔,因此也更容易檢查雷滋。

推薦:

if (!error) {
    return success;
}

反對:

if (!error)
    return success;

if (!error) return success;

三目運算符

三目運算符不撑,? ,只有當它可以增加代碼清晰度或整潔時才使用晤斩。單一的條件都應該優(yōu)先考慮使用焕檬。多條件時通常使用 if 語句會更易懂,或者重構(gòu)為實例變量澳泵。

推薦:

result = a > b ? x : y;

反對:

result = a > b ? x = c > d ? c : d : y;

錯誤處理

當引用一個返回錯誤參數(shù)(error parameter)的方法時实愚,應該針對返回值,而非錯誤變量兔辅。

推薦:

NSError *error;
if (![self trySomethingWithError:&error]) {
    // 處理錯誤
}

反對:

NSError *error;
[self trySomethingWithError:&error];
if (error) {
    // 處理錯誤
}

一些蘋果的 API 在成功的情況下會寫一些垃圾值給錯誤參數(shù)(如果非空)腊敲,所以針對錯誤變量可能會造成虛假結(jié)果(以及接下來的崩潰)。

方法

在方法簽名中维苔,在 -/+ 符號后應該有一個空格兔仰。方法片段之間也應該有一個空格。
方法名: 多個參數(shù)名前的方法要有描述性的關鍵字,并且不要包含and字段

推薦:

- (void)setExampleText:(NSString *)text image:(UIImage *)image;

方法命名

小寫第一個單詞的首字符蕉鸳,大寫隨后單詞的首字符乎赴,不使用前綴。有兩種例外情況:
1潮尝,方法名以廣為人知的大寫字母縮略詞(如TIFF or PDF)開頭榕吼;
2,私有方法可以使用統(tǒng)一的前綴來分組和辨識

表示對象行為的方法勉失,名稱以動詞開頭

推薦

- (void)invokeWithTarget:(id)target:
- (void)selectTabViewItem:(NSTableViewItem *)tableViewItem

方法返回接收者的某個屬性羹蚣,直接用屬性名稱命名。

推薦

- (NSSize)cellSize; 

參數(shù)前面的單詞要能描述該參數(shù)

推薦

- (void)sendAction:(SEL)aSelector to:(id)anObject forAllCells:(BOOL)flag; 

方法分組

使用 #pragma mark - 方法對類的方法進行分組

#pragma mark - 聲明周期
- (void)viewDidLoad {
    [super viewDidLoad];
}

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

#pragma mark - 初始化對象懶加載
- (NSMutableArray *)dataSource{
    if (!_dataSource) {
    _dataSource = [NSMutableArray array];
    }
    return _dataSource;
}

- (NSMutableArray *)tempDataArray{
    if (!_tempDataArray) {
    _tempDataArray = [NSMutableArray array];
    }
    return _tempDataArray;
}

變量

變量名應該盡可能命名為描述性的乱凿。除了 for() 循環(huán)外顽素,其他情況都應該避免使用單字母的變量名。
星號表示指針屬于變量徒蟆,例如:NSString *text 不要寫成 NSString* text 或者 NSString * text 胁出,常量除外。
盡量定義屬性來代替直接使用實例變量段审。除了初始化方法(init全蝶, initWithCoder:,等)寺枉, dealloc 方法和自定義的 setters 和 getters 內(nèi)部抑淫,應避免直接訪問實例變量。更多有關在初始化方法和 dealloc 方法中使用訪問器方法的信息姥闪,參見這里始苇。

推薦:

@interface NYTSection : NSObject

@property (nonatomic) NSString *headline;

@end

反對:

@interface NYTSection : NSObject {
    NSString *headline;
}

變量限定符

當涉及到在 ARC 中被引入變量限定符時,
限定符 (__strong, __weak, __unsafe_unretained, __autoreleasing) 應該位于星號和變量名之間筐喳,如:NSString * __weak text催式。

命名

盡可能遵守蘋果的命名約定函喉,尤其那些涉及到內(nèi)存管理規(guī)則,(NARC)的蓄氧。

長的和描述性的方法名和變量名都不錯函似,采用小駝峰命名方式。

推薦:

UIButton *settingsButton;

反對:

UIButton *setBut;

類名和常量應該始終使用字母的前綴(例如 Lenz)喉童,但 Core Data 實體名稱可以省略撇寞。為了代碼清晰,常量應該使用相關類的名字作為前綴并使用駝峰命名法堂氯。

推薦:

static const NSTimeInterval LenzArticleViewControllerNavigationFadeAnimationDuration = 0.3;

反對:

static const NSTimeInterval fadetime = 1.7;

屬性和局部變量應該使用駝峰命名法并且首字母小寫蔑担。

為了保持一致,實例變量應該使用駝峰命名法命名咽白,并且首字母小寫啤握,以下劃線為前綴。這與 LLVM 自動合成的實例變量相一致晶框。
如果 LLVM 可以自動合成變量排抬,那就讓它自動合成。

推薦:

@synthesize descriptiveVariableName = _descriptiveVariableName;

反對:

id varnm;

注釋

當需要的時候授段,注釋應該被用來解釋 為什么 特定代碼做了某些事情蹲蒲。所使用的任何注釋必須保持最新否則就刪除掉。
通常應該避免一大塊注釋侵贵,代碼就應該盡量作為自身的文檔届搁,只需要隔幾行寫幾句說明。這并不適用于那些用來生成文檔的注釋窍育。

屬性注釋

/** 頭像image */
@property (nonatomic, strong) UIimageView *headerImage;

方法聲明注釋

  /**   
   * @brief 登錄驗證 3   
   * @param personId 用戶名
   * @param password 密碼 
   * @param complete 執(zhí)行完畢的block 
   * @return 
   */
+ (void)loginWithPersonId:(NSString *)personId password:(NSString *)password complete:(void (^)(CheckLogon *result))complete;

宏定義

全部大寫 卡睦, 單詞間用_分隔 (不帶參數(shù))
推薦

#define IS_IPHONE_VERSION @"9.0"

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

#define kStatusCode @"0000000"

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

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

init 和 dealloc

dealloc 方法應該放在實現(xiàn)文件的最上面漱抓,并且剛好在 @synthesize@dynamic 語句的后面表锻。在任何類中,init 都應該直接放在 dealloc 方法的下面辽旋。

init 方法的結(jié)構(gòu)應該像這樣:

- (instancetype)init {
    self = [super init]; // 或者調(diào)用指定的初始化方法
    if (self) {
        // Custom initialization
    }
    return self;
}

字面量

每當創(chuàng)建 NSString浩嫌, NSDictionaryNSArray补胚,和 NSNumber 類的不可變實例時,都應該使用字面量追迟。要注意 nil 值不能傳給 NSArrayNSDictionary 字面量溶其,這樣做會導致崩潰。

推薦:

NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul"];
NSDictionary *productManagers = @{@"iPhone": @"Kate", @"iPad": @"Kamal", @"Mobile Web": @"Bill"};
NSNumber *shouldUseLiterals = @YES;
NSNumber *buildingZIPCode = @10018;

反對:

NSArray *names = [NSArray arrayWithObjects:@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul", nil];
NSDictionary *productManagers = [NSDictionary dictionaryWithObjectsAndKeys: @"Kate", @"iPhone", @"Kamal", @"iPad", @"Bill", @"Mobile Web", nil];
NSNumber *shouldUseLiterals = [NSNumber numberWithBool:YES];
NSNumber *buildingZIPCode = [NSNumber numberWithInteger:10018];

CGRect 函數(shù)

當訪問一個 CGRectx敦间, y瓶逃, width束铭, height 時,應該使用CGGeometry 函數(shù)代替直接訪問結(jié)構(gòu)體成員厢绝。蘋果的 CGGeometry 參考中說到:

All functions described in this reference that take CGRect data structures as inputs implicitly standardize those rectangles before calculating their results. For this reason, your applications should avoid directly reading and writing the data stored in the CGRect data structure. Instead, use the functions described here to manipulate rectangles and to retrieve their characteristics.

推薦:

CGRect frame = self.view.frame;

CGFloat x = CGRectGetMinX(frame);
CGFloat y = CGRectGetMinY(frame);
CGFloat width = CGRectGetWidth(frame);
CGFloat height = CGRectGetHeight(frame);

反對:

CGRect frame = self.view.frame;

CGFloat x = frame.origin.x;
CGFloat y = frame.origin.y;
CGFloat width = frame.size.width;
CGFloat height = frame.size.height;

常量

常量首選內(nèi)聯(lián)字符串字面量或數(shù)字契沫,因為常量可以輕易重用并且可以快速改變而不需要查找和替換。常量應該聲明為 static 常量而不是 #define 昔汉,除非非常明確地要當做宏來使用懈万。

推薦:

static NSString * const LenzAboutViewControllerCompanyName = @"The Lenz Company";

static const CGFloat LenzImageThumbnailHeight = 50.0;

反對:

#define CompanyName @"The Lenz Company"

#define thumbnailHeight 2

枚舉類型

當使用 enum 時,建議使用新的基礎類型規(guī)范靶病,因為它具有更強的類型檢查和代碼補全功能』嵬ǎ現(xiàn)在 SDK 包含了一個宏來鼓勵使用使用新的基礎類型 - NS_ENUM()

推薦:

typedef NS_ENUM(NSInteger, LenzAdRequestState) {
    LenzAdRequestStateInactive,
    LenzAdRequestStateLoading
};

位掩碼

當用到位掩碼時,使用 NS_OPTIONS 宏娄周。

舉例:

typedef NS_OPTIONS(NSUInteger, LenzAdCategory) {
    LenzAdCategoryAutos      = 1 << 0,
    LenzAdCategoryJobs       = 1 << 1,
    LenzAdCategoryRealState  = 1 << 2,
    LenzAdCategoryTechnology = 1 << 3
};

私有屬性

私有屬性應該聲明在類實現(xiàn)文件的延展(匿名的類目)中涕侈。

推薦:

@interface LenzAdvertisement ()

@property (nonatomic, strong) GADBannerView *googleAdView;
@property (nonatomic, strong) ADBannerView *iAdView;
@property (nonatomic, strong) UIWebView *adXWebView;

@end

圖片命名

命名規(guī)則的基本思想是把文件名分成三部分,第一部分是圖片的邏輯歸屬分類煤辨,第二部分是圖片的表現(xiàn)內(nèi)容裳涛,第三部分是圖片的內(nèi)容的類型,有些圖片還會有第四部分众辨,表示圖片表現(xiàn)的狀態(tài)端三。
1、用英文命名泻轰,不用拼音
2技肩、每一部分用下劃線分隔
3、圖片名中兩倍圖在名字最后要加@2x浮声,三倍圖在名字最后要加@3x

推薦:

  • tab_button_search_normal@2x.png
    home_imageview_banner@2x.png
    tab_button_news_normal@3x.png

布爾

因為 nil 解析為 NO虚婿,所以沒有必要在條件中與它進行比較。永遠不要直接和 YES 進行比較泳挥,因為 YES 被定義為 1然痊,而 BOOL 可以多達 8 位。

這使得整個文件有更多的一致性和更大的視覺清晰度屉符。

推薦:

if (!someObject) {
}

反對:

if (someObject == nil) {
}

對于 BOOL 來說, 這有兩種用法:

if (isAwesome)
if (![someObject boolValue])

反對:

if ([someObject boolValue] == NO)
if (isAwesome == YES) // 永遠別這么做

如果一個 BOOL 屬性名稱是一個形容詞剧浸,屬性可以省略 “is” 前綴,但為 get 訪問器指定一個慣用的名字矗钟,例如:

@property (assign, getter=isEditable) BOOL editable;

內(nèi)容和例子來自 Cocoa 命名指南 唆香。

單例

單例對象應該使用線程安全的模式創(chuàng)建共享的實例。

+ (instancetype)sharedInstance {
    static id sharedInstance = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });

    return sharedInstance;
}

這將會預防有時可能產(chǎn)生的許多崩潰吨艇。

導入

如果有一個以上的 import 語句躬它,就對這些語句進行分組。每個分組的注釋是可選的东涡。
注:對于模塊使用 @import 語法冯吓。

// Frameworks
@import QuartzCore;

// Models
#import "NYTUser.h"

// Views
#import "NYTButton.h"
#import "NYTUserView.h"

Xcode 工程

為了避免文件雜亂倘待,物理文件應該保持和 Xcode 項目文件同步。Xcode 創(chuàng)建的任何組(group)都必須在文件系統(tǒng)有相應的映射组贺。為了更清晰凸舵,代碼不僅應該按照類型進行分組,也可以根據(jù)功能進行分組失尖。

如果可以的話啊奄,盡可能一直打開 target Build Settings 中 "Treat Warnings as Errors" 以及一些額外的警告。如果你需要忽略指定的警告,使用 Clang 的編譯特性 雹仿。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末增热,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子胧辽,更是在濱河造成了極大的恐慌峻仇,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件邑商,死亡現(xiàn)場離奇詭異摄咆,居然都是意外死亡,警方通過查閱死者的電腦和手機人断,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門吭从,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人恶迈,你說我怎么就攤上這事涩金。” “怎么了暇仲?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵步做,是天一觀的道長。 經(jīng)常有香客問我奈附,道長全度,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任斥滤,我火速辦了婚禮将鸵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘佑颇。我一直安慰自己顶掉,他們只是感情好,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布挑胸。 她就那樣靜靜地躺著一喘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嗜暴。 梳的紋絲不亂的頭發(fā)上凸克,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音闷沥,去河邊找鬼萎战。 笑死,一個胖子當著我的面吹牛舆逃,可吹牛的內(nèi)容都是我干的蚂维。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼路狮,長吁一口氣:“原來是場噩夢啊……” “哼虫啥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起奄妨,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤涂籽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后砸抛,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體评雌,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年直焙,在試婚紗的時候發(fā)現(xiàn)自己被綠了景东。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡奔誓,死狀恐怖斤吐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情厨喂,我是刑警寧澤和措,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站杯聚,受9級特大地震影響臼婆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜幌绍,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一颁褂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧傀广,春花似錦颁独、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春靠柑,著一層夾襖步出監(jiān)牢的瞬間寨辩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工歼冰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留靡狞,地道東北人。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓隔嫡,卻偏偏與公主長得像甸怕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子腮恩,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355