前言
為什么要制定一套Objective-C在iOS APP開發(fā)的規(guī)范要求?我們都知道,一款A(yù)PP開發(fā)出來之后,還有冗長的維護和迭代過程,而且在APP的開發(fā)過程中,絕大多數(shù)都是團隊開發(fā),如果在這期間沒有一套統(tǒng)一、規(guī)范的開發(fā)標(biāo)準(zhǔn),就很難保證代碼風(fēng)格的一致性,可讀性降低 ,團隊開發(fā) 和 后期維護 都會帶比較嚴(yán)重的后果。
如果在APP的開發(fā)過程中都以這個標(biāo)準(zhǔn)去執(zhí)行,代碼的可讀性、開發(fā)期間的溝通、后期維護都會非常順暢。
開發(fā)標(biāo)準(zhǔn)(規(guī)范)制定依據(jù)
既然是標(biāo)準(zhǔn),可能就會有人質(zhì)疑了,你制定的這套標(biāo)準(zhǔn)有什么依據(jù)?
首先這個標(biāo)準(zhǔn)不是由個人制定,也不是由哪一個團隊制定,而是根據(jù)Apple官方文檔以及Xcode 中提供的一些SourceCode 為參考來制定的。
當(dāng)然還有很多認(rèn)可度極高的文檔:
The Objective-C Programming Language
Cocoa Fundamentals Guid
Coding Guidelines for Cocoa
iOS App Programming Guide
規(guī)范正文
一 . 關(guān)于命名
命名要求含義清楚,盡量做到不需要注釋也能了解其作用;
不要偷懶,勤加注釋;
命名使用英語,不要使用拼音、數(shù)字。
1. 類的命名
大駝峰式命名:每個單詞的首字母都采用大寫字母。
前綴以約定的標(biāo)志性字母開頭,中間以功能英文單詞命名,再加上全名后綴(不得簡寫)。
例一:GTHomePageViewController // Controller層控制器類名
例二:GTUserInfoModel //Model層類名
例三:GTNewsListsTableViewCell //View層TableViewCell的命名
例三:GTAlertSheetViewDelegate //代理方法中Delegate的命名
例三:GTAlertSheetViewDateSource //代理方法中DateSource的命名
2. Foundation成員變量的命名
小駝峰式命名:第一個單詞以小寫字母開始,后面的單詞的首字母全部大寫。
例一: .m 文件中聲明的私有變量
{
NSString * _somePrivateVariable;
}
例二:property變量
@property (nonatomic, strong) NSString *userName;
3. UIKit成員變量的命名
小駝峰式命名:第一個單詞以小寫字母開始,后面的單詞的首字母全部大寫。此外命名必須是 描述性的單詞+變量類型,一目了然。
變量類型運行使用通用的縮寫,若縮寫不是公認(rèn)的,不推薦。
例一: .m 文件中聲明的私有變量
{
UILabel * _nameLabel;
UIButton * _nameBtn
}
例二:property變量
@property (nonatomic, strong) UILabel * nameLb;
@property (nonatomic, strong) UIButton * nameButton;
4. 宏命名
- 情況一:全部大寫,單詞間用 _ 分隔。[不帶參數(shù)] [不推薦使用]
- 情況二:以字母 k 開頭,后面遵循大駝峰命名。[不帶參數(shù)]
- 情況三:以字母 k 開頭,小駝峰命名。[帶參數(shù)]
推薦 使用 [情況二] 和 [情況三]。
例一:情況一
#define THIS_IS_AN_MACRO @"THIS_IS_AN_MACRO"
例二:情況二
#define kWidth self.frame.size.width
例三:情況三
#define kGetImageUrl(url) [NSURL URLWithString:[NSString stringWithFormat:@"%@%@",kBaseUrl,url]]
5. Xib的命名
Xib文件的命名與其對應(yīng)的.h文件保持相同
二. 枚舉Enum
為什么要把枚舉單獨拿出來說?
我們都知道,代碼中很多需要根據(jù)狀態(tài)值來進行分類的,比如服務(wù)器傳來一個狀態(tài)參數(shù)1 、2、 3等等值,1代表交易成功、2代表已經(jīng)付款、3代表未付款等等,這里我們在代碼編寫過程中直接用if else 來分類就low爆了,不僅代碼的可讀性低,而且維護起來非常不便。而且如果狀態(tài)值代表的意義還有改變的,需要來怎么去處理?如果開發(fā)初期就規(guī)定使用枚舉,這些問題就會很容易的解決。
- 必須使用 NS_ENUM 或者 NS_OPTIONS
- Enum類型的命名與類的命名規(guī)則一致
- Enum中枚舉內(nèi)容的命名需要以該Enum類型名稱開頭
typedef NS_ENUM(NSUInteger, ShareUISelcetIndex) {
ShareUISelcetIndexDefault = SSDKPlatformTypeUnknown, // 默認(rèn)
ShareUISelcetIndexWechatFriend = SSDKPlatformSubTypeWechatSession, // 微信好友
ShareUISelcetIndexWechatGroup = SSDKPlatformSubTypeWechatTimeline, //微信朋友圈
ShareUISelcetIndexQQFriend = SSDKPlatformSubTypeQQFriend, //QQ好友
ShareUISelcetIndexQQZone = SSDKPlatformSubTypeQZone, //QQ空間
ShareUISelcetIndexSina= SSDKPlatformTypeSinaWeibo, //新浪
ShareUISelcetIndexRefresh, // 刷新
ShareUISelcetIndexCopyToPad, // 復(fù)制到剪切板
};
三. 方法的命名
1.普通方法的命名
方法使用小駝峰法命名。
一個規(guī)范的方法讀起來應(yīng)該像一句完整的話(OC語言的風(fēng)格)。讀過之后便知函數(shù)的作用。
執(zhí)行性的方法應(yīng)該以動詞開頭,小寫字母開頭。
返回性的方法應(yīng)該以返回的內(nèi)容開頭。
例一:執(zhí)行性
-(void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
例二:返回性
-(instancetype)arrayWithArray:(NSArray *)array;
2.Delegate方法的命名
- 類的實例必須為回調(diào)方法的參數(shù)之一;
- 回調(diào)方法的參數(shù)只有類自己的情況,方法名要符合實際含義;
- 以類的名字開頭(回調(diào)方法存在兩個以上參數(shù)的情況)以表明此方法是屬于哪個類的;
- 推薦使用did和will通知Delegate已經(jīng)發(fā)生的變化或?qū)⒁l(fā)生的變化.
類的實例必須為回調(diào)方法的參數(shù)之一
-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
回調(diào)方法的參數(shù)只有類自己的情況,方法名要符合實際含義;
-(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
以類的名字開頭(回調(diào)方法存在兩個以上參數(shù)的情況)以表明此方法是屬于哪個類的
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
推薦使用did和will通知Delegate已經(jīng)發(fā)生的變化或?qū)⒁l(fā)生的變化.
-(NSIndexPath*)tableView:(UITableView*)tableView willSelectRowAtIndexPath:(NSIndexPath*)indexPath;
-(void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath;
3. 對方法進行分組(#pragma mark -)
使用 #pragma mark - 方式對類的方法進行分組,會使代碼分區(qū),看起來非常賞心悅目。
如圖:
4. 代碼縮進
[小技巧]直接強文件中的代碼剪切,再復(fù)制粘貼進來。 Xcode 會自動對代碼進行縮進處理。
Method與Method之間至少空一行,最好是最多也只空一行。
5. 大括號寫法
- 左括號跟在第一行后邊
- 任何需要寫大括號的部分,不得省略
錯誤示例:
- (void)wrongExample{
BOOL someCondition = YES;
if (someCondition)
NSLog(@"this is wrong!!!");
}
規(guī)范示例:
- (void)rightExample{
BOOL someCondition = YES;
if (someCondition){
NSLog(@"this is wrong!!!");
}
}
四. 注釋
1. 屬性注釋
- 推薦使用 注釋統(tǒng)一采用文檔注釋方式:/** description */ ,即Xcode 8 提供的快捷鍵注釋。Xcode 7 版本采用這種注釋在調(diào)用該屬性的時候,會提示出這個描述,但現(xiàn)在Xcode 8 似乎沒有。
- 其他注釋 // Description
@interface ShareUIView : UIView
/**
block one
*/
@property (nonatomic,copy) void(^cellClickblock)(ShareUISelcetIndex index);
@property (nonatomic,copy) void(^cellPushblock)(ShareUISelcetIndex index); // block two
@end
2. 方法聲明注釋
- 推薦使用 Xcode 8 提供的快捷鍵注釋。
/**
單例模式
*
@return 單例對象
*/
+(LeeAlertSheetView *)sharedInstacne;
/**
* 創(chuàng)建提示框(Alert 可變參數(shù)版)
*
* @param title 標(biāo)題
* @param message 提示內(nèi)容
* @param cancelTitle 取消按鈕(無操作,為nil則只顯示一個按鈕)
* @param vc VC iOS8及其以后會用到
* @param confirm 點擊按鈕的回調(diào)(取消按鈕的Index是cancelIndex -1)
* @param buttonTitles 按鈕(為nil,默認(rèn)為"確定",傳參數(shù)時必須以nil結(jié)尾,否則會崩潰)
*/
- (void)showAlert:(NSString *)title message:(NSString *)message cancelTitle:(NSString *)cancelTitle viewController:(UIViewController *)vc confirm:(myAlertSheetViewBlock)confirm buttonTitles:(NSString *)buttonTitles, ... NS_REQUIRES_NIL_TERMINATION;
五. 三目運算符
我們直接就開始舉個栗子了
- (void)rightExample{
BOOL someCondition = YES;
if (someCondition){
self.myView.alpha = 0.5;
}else{
self.myView.alpha = 0.1;
}
}
這里如果用三目運算符怎么寫?
- (void)rightExample{
self.myView.alpha = someCondition ? 0.5: 0.1
}
六. 多使用常量(const),代替宏(define)
可以參考這篇文章iOS 宏(define)與常量(const)的正確使用
比如定義一個常量又不想被修改應(yīng)該這樣:
static NSString * const HSCoder = @"漢斯哈哈哈";
static NSString * const collectionCellIdentifier = @"ShareUICollectionViewCell";
七. 其他
- 在屬性命名中,如果類的全名太長,可以使用一些縮寫,但這些縮寫必須是大家公認(rèn),沒有任何歧義的。(比如:nav,bg,btn,lb,tf等)。
- 在函數(shù)命名中,推薦使用一些經(jīng)典的操作應(yīng)該使用約定的動詞,如initWith,insert,remove,replace,add等等。
- 對于類的method: 左括號另起一行寫(遵循蘋果官方文檔)。這一要求可以使用,但不強制使用,具體可以根據(jù)團隊開發(fā)要求來限定,因為比如我們創(chuàng)建一個UIViewController,里面的方法均沒有執(zhí)行這一要求,所以我們也不強制執(zhí)行。
如有紕漏,歡迎留言狂噴
沒有傷害,就沒有進步。
- QQ 375701847。