Objective-C Coding Guide

Objective-C Coding Guide


版本: 1.1

修訂: iOS茄子快傳組

時(shí)間: 2017/08/28


總則: 英文單詞拼寫一定要正確、交流發(fā)音一定要準(zhǔn)確嚷闭、動(dòng)名詞使用一定要恰當(dāng)


命名

  • 類方法名、對(duì)象方法名、成員屬性名、臨時(shí)變量名 要遵循 駝峰 規(guī)則集币。首字母小寫,其余單詞首字母大寫

  • 類文件名單詞首字母全部大寫翠忠,注意添加項(xiàng)目前綴鞠苟。

  • 類方法名、對(duì)象方法名秽之、成員屬性名当娱、臨時(shí)變量名單詞不可簡寫,要寫的有意義考榨。

正確:
- (void)resetBarAttribute:(UIColor *)normal highlight:(UIColor *)highlight font:(UIFont *)font
{
    for (UIButton *bar in self.bars) {
        [self setBar:bar :normal :highlight :font];
    }
}

不建議:
- (void)resetBarAttribute:(UIColor *)normal :(UIColor *)highlight :(UIFont *)font
{
    for (UIButton *bar in self.bars) {
        [self setBar:bar :normal :highlight :font];
    }
}

  • 為了避免混淆造成不必要的問題跨细,自己聲明的臨時(shí)變量或者全局靜態(tài)變量,不應(yīng)該以 _ 下劃線開頭河质,因?yàn)橄到y(tǒng)為成員屬性生成的成員變量是以 _ 下劃線開頭冀惭。更不應(yīng)該用系統(tǒng)自有的變量或方法來聲明一個(gè)變量 比如 *new

注釋

  • 注釋應(yīng)在代碼的上方或者右方震叙,不可在下方

項(xiàng)目結(jié)構(gòu)

  • 工具類的命名要為 xxxTool 或者 xxxUtil,不建議 xxxHelper

  • 類文件盡量放在指定的文件夾中散休,文件夾的名稱不建議使用復(fù)數(shù)媒楼,文件夾名稱不建議加項(xiàng)目前綴

  • 為了避免文件雜亂,物理文件應(yīng)該保持和 Xcode 項(xiàng)目文件同步溃槐。Xcode 創(chuàng)建的任何組(group)都必須在文件系統(tǒng)有相應(yīng)的物理映射匣砖。為了更清晰科吭,代碼可按照類型進(jìn)行分組昏滴,也可按功能進(jìn)行分組。


代碼格式化

  • 空格的添加

    • +对人、-谣殊、*/牺弄、?:

    • 類方法姻几、對(duì)象方法的調(diào)用

    正確:
    [[NSObject alloc] init];
    
    不建議:
    [[NSObject alloc]init];
    
    
    • 類方法、對(duì)象方法的聲明和調(diào)用
    聲明:
    - (void)run;
    
    + (void)personWithAge:(NSUInteger)age;
    
    調(diào)用:
    - (void)run {
    
    }
    
    + (void)personWithAge:(NSUInteger)age {
    
    }
    
    

    (* 注意:類方法對(duì)象方法在.m中實(shí)現(xiàn)的時(shí)候不允許復(fù)制势告,要用 +- 直接提示出方法來寫蛇捌,以免出現(xiàn)方法實(shí)現(xiàn)末尾出現(xiàn) ; 分號(hào)的情況 *, 如下所示:)

    + (void)personWithAge:(NSUInteger)age; {
    
    }
    
    
  • iffor咱台、while络拌、trycatch 等語句自占一行回溺,執(zhí)行語句不得緊跟其后春贸,并且條件和這些關(guān)鍵詞之后都有空格。_ (建議:不論執(zhí)行語句有多少都要加 “{ }”) _ 遗遵。這樣可以防止書寫和修改代碼時(shí)出現(xiàn)失誤萍恕。

  • 宏要全部大寫,并且要用必要的下劃線分隔開單詞车要;常量要用字母k開頭后面單詞首字母全部大寫

#define MAX_SIZE 30

static const NSUInteger kUsernameRow = 0;

  • 一個(gè)方法應(yīng)該太多行允粤,暫定不要超過 100 行。如果其中的過程沒有提取為獨(dú)立方法的必要翼岁,則不必限制長度

  • 代碼行最大長度宜控制在 80 個(gè)字符以內(nèi)类垫。代碼行不要過長,否則眼睛看不過來登澜,不過此規(guī)則可以視情況適當(dāng)放寬阔挠。

不要出現(xiàn)下面這樣:

/**用于獲取每個(gè)section應(yīng)當(dāng)返回的cell個(gè)數(shù)*/
-(NSInteger)getSectionCount:(NSDictionary*)dict
{
    return (dict[kPhotos]==nil?0:[dict[kPhotos] count]+1)+(dict[kMusics]==nil?0:[dict[kMusics] count]+1)+(dict[kFiles]==nil?0:[dict[kFiles] count]+1)+(dict[kVideos]==nil?0:[dict[kVideos] count]+1)+(dict[kContacts]==nil?0:[dict[kContacts] count]+1)+(dict[kFloders]==nil?0:[dict[kFloders] count]+1);
}

  • 空行的使用,要內(nèi)函數(shù)內(nèi)模塊來分脑蠕。適當(dāng)?shù)奶砑涌招泄汉常梢允谴a結(jié)構(gòu)更為清晰跪削,減少錯(cuò)誤。

代碼組織

  • 可變數(shù)組迂求、可變字典等可變的類型的命名碾盐,一定要以 M 結(jié)尾
NSMutableArray *mediaItemsArrM = [NSMutableArray array];

字符串后     xxxStr/xxxStrM

集合后     xxxArray/xxxArrayM  xxxArr/xxxArrM

字典后     xxxDict/xxxDictM

  • 可變數(shù)組和可變字典只要元素類型確定,一定要寫上 泛型 指定類型揩局。如果元素類型是多態(tài)可變的可不寫
NSMutableArray<ASMediaItem *> *mediaItemsArrM = [NSMutableArray array];

  • 可變數(shù)組毫玖、可變字典等可變的類型不可用于返回值和參數(shù),一定要做出及時(shí)的轉(zhuǎn)換后再使用

  • 類方法和對(duì)方法聲明的時(shí)候凌盯,一定要指定參數(shù)或返回值是否可 nil付枫,做到及時(shí)斷言處理

- (nonnull NSArray<NSArray<ASMediaItem *> *> *)selectMediaItemsArr;

- (void)saveWithMediaItemsArr:(nonnull NSArray<ASMediaItem *> *)mediaItemsArr;


  • 不可使用魔鬼數(shù)字和魔鬼字母

  • 對(duì)象在使用前注意判 nil,特別是將對(duì)象添加到可變數(shù)組和可變字典的時(shí)候驰怎。還有一些方法參數(shù)沒有明確說不可為 nil阐滩,但依然會(huì)崩潰,比如:

[NSURL fileURLWithPath:nil];

[[NSFileManager defaultManager] createSymbolicLinkAtURL:nil withDestinationURL:nil error:nil];

[NSJSONSerialization dataWithJSONObject:nil options:0 error:nil];


  • 修飾符的位置:為便于理解县忌,應(yīng)當(dāng)將修飾符 *& 緊靠變量或參數(shù)
@property (nonatomic, copy, readonly, nonnull) NSString *layerId;

CFStringRef FileBlockMD5HashCreateWithPath(NSString *filePath)

UpdateHash(&hashObject, fileHandle, startIndex, blockSize);

[[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self accessToTheMainFilePath] error:&error];


其他

  • 枚舉類型的定義

    • NS_ENUM 枚舉項(xiàng)的值為 NSInteger掂榔,NS_OPTIONS 枚舉項(xiàng)的值為 NSUInteger。像下面這樣:
    typedef NS_ENUM(NSInteger, IJKMPMoviePlaybackState) {
        IJKMPMoviePlaybackStateStopped = 0,
        IJKMPMoviePlaybackStatePlaying,
        IJKMPMoviePlaybackStatePaused,
        IJKMPMoviePlaybackStateInterrupted,
        IJKMPMoviePlaybackStateSeekingForward,
        IJKMPMoviePlaybackStateSeekingBackward
    };
    
    
    typedef NS_OPTIONS(NSUInteger, UISwipeGestureRecognizerDirection) {
      UISwipeGestureRecognizerDirectionNone = 0,  //值為0
      UISwipeGestureRecognizerDirectionRight = 1 << 0,  //值為2的0次方
      UISwipeGestureRecognizerDirectionLeft = 1 << 1,  //值為2的1次方
      UISwipeGestureRecognizerDirectionUp = 1 << 2,  //值為2的2次方
      UISwipeGestureRecognizerDirectionDown = 1 << 3  //值為2的3次方};
    
    
    • NS_ENUM定義 通用枚舉症杏,NS_OPTIONS 定義位移枚舉
    位移枚舉即是在你需要的地方可以同時(shí)存在多個(gè)枚舉值如這樣:
    UISwipeGestureRecognizer *swipeGR = [[UISwipeGestureRecognizer alloc] init];
    swipeGR.direction = UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight;
    //這里幾個(gè)枚舉項(xiàng)同時(shí)存在表示它的方向同時(shí)包含1.向下2.向左3.向右
    
    而NS_ENUM定義的枚舉不能幾個(gè)枚舉項(xiàng)同時(shí)存在装获,只能選擇其中一項(xiàng),像這樣:
    NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
    paragraph.baseWritingDirection = NSWritingDirectionNatural;
    
    
  • 類方法新建對(duì)象
ASAdWrapper 類

+ (nonnull instancetype)wrapperWithLayerId:(nonnull NSString *)layerId fullAdId:(nonnull NSString *)fullAdId expiredDuration:(long long)expiredDuration;

ASAdInfo 類

+ (nonnull instancetype)infoWithLayerId:(nonnull NSString *)layerId fullAdId:(nullable NSString *)fullAdId;


  • 對(duì)象方法新建對(duì)象
ASAdWrapper 類

- (instancetype)initWithLayerId:(NSString *)layerId fullAdId:(NSString *)fullAdId expiredDuration:(long long)expiredDuration AdObject:(NSObject *)adObj adKeyword:(NSString *)adKeyword;

ASAdInfo 類

+ (instancetype)initWithLayerId:(NSString *)layerId fullAdId:(NSString *)fullAdId;

  • 代理方法的命名

    • 用delegate做后綴

    • 用optional修飾可以不實(shí)現(xiàn)的方法厉颤,用required修飾必須實(shí)現(xiàn)的方法

    • 當(dāng)你的委托的方法過多, 可以拆分?jǐn)?shù)據(jù)部分和其他邏輯部分, 數(shù)據(jù)部分用dataSource做后綴

    • 使用did和will通知Delegate已經(jīng)發(fā)生的變化或?qū)⒁l(fā)生的變化

    • 類的實(shí)例必須為回調(diào)方法的參數(shù)之一

    • 回調(diào)方法的參數(shù)只有類自己的情況穴豫,方法名要符合實(shí)際含義

    • 回調(diào)方法存在兩個(gè)以上參數(shù)的情況,以類的名字開頭走芋,以表明此方法是屬于哪個(gè)類的

@protocol UITableViewDataSource

@required

//回調(diào)方法存在兩個(gè)以上參數(shù)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;

@optional

//回調(diào)方法的參數(shù)只有類自己
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; // Default is 1 if not implemented

@end

@protocol UITableViewDelegate

@optional

//使用did和will通知Delegate
- (nullable NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath;

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

@end

  • .h 文件的組織:系統(tǒng)頭文件放在前面绩郎,自定義的頭文件放在后面,接著是 @class, 中間空行; 成員屬性寫在上方翁逞,方法寫在下方
#import <UIKit/UIKit.h>

#import "MemberVariable.h"

@class ASUserInfo;

@interface DateilViewController : UIViewController
{
    //變量
    NSString *_dataString;
}


//屬性
@property (nonatomic, strong) NSDictionary *supplyDateilDict;
@property (nonatomic, strong) NSMutableArray *supplyArray;

//方法
- (void)handleData;
- (void)createView;


@end

  • .h 文件中引用要使用 @class肋杖,在.m引用要使用 #import "xxx.h",加快編譯速度
#import <Foundation/Foundation.h>
#import <uShareitSDK/AndyDictStore.h>
@class ASAdWrapper;
@class ASAdInfo;

@interface ASAdCache : NSObject

SingletonH(Cache);

- (void)pushToAdCacheWithAdWrappersArray:(nonnull NSArray<ASAdWrapper *> *)adWrappersArr;

- (nullable NSArray<ASAdWrapper *> *)popFromAdCacheWithAdInfo:(nonnull ASAdInfo *)adInfo;

- (nullable NSArray<ASAdWrapper *> *)popFromAdCacheWithAdInfo:(nonnull ASAdInfo *)adInfo supportUseMinCount:(BOOL)supportUseMinCount;

- (BOOL)hasAdCacheWithAdInfo:(nonnull ASAdInfo *)adInfo;

@end

  • 新建一個(gè)對(duì)象不建議使用 new挖函,太過暴力状植,要使用對(duì)應(yīng)的類方法和對(duì)象方法來新建對(duì)象。盡管很多時(shí)候能用 new 代替 alloc init 方法怨喘,但這可能會(huì)導(dǎo)致調(diào)試內(nèi)存時(shí)出現(xiàn)不可預(yù)料的問題津畸。Cocoa的規(guī)范就是使用 alloc init 方法,使用 new 會(huì)讓一些讀者困惑必怜。

  • 類方法肉拓、對(duì)象方法返回對(duì)象自身要使用 instancetype 而不是使用 id。這樣IDE會(huì)幫你檢查類型梳庆,及時(shí)顯示警告暖途,減少錯(cuò)誤卑惜。

  • 屬性特性:weakstrong驻售、atomic露久、nonatomicreadonly欺栗、
    getter毫痕、setternonnull迟几、nullable

@property (nonatomic, copy, readonly, nonnull) NSString *layerId; 

@property (nonatomic, copy, readonly, nullable) NSString *fullAdId;

@property (nonatomic, copy, readonly, nonnull) NSString *style; 

@property (nonatomic, copy, readonly, nullable) NSString *placementId; 

@property (nonatomic, strong, nonnull) NSMutableSet<NSString *> *excludeKeywordsSetM;

@property (nonatomic, assign, readonly) NSUInteger adPullCount; 

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

  • 使用//TODO:說明 標(biāo)記一些未完成的或完成的不盡如人意的地方
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //TODO:增加初始化
    return YES;
}

  • 函數(shù)

    • 一個(gè)函數(shù)只做一件事(單一原則),每個(gè)函數(shù)的職責(zé)都應(yīng)該劃分的很明確(就像類一樣)

    • 對(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ù)梯啤。一個(gè)函數(shù)內(nèi)的不清晰(邏輯判斷比較多,行數(shù)較多)的那片代碼存哲,往往可以被提取出去,構(gòu)成一個(gè)新的函數(shù)七婴,然后在原來的地方調(diào)用它這樣你就可以使用有意義的函數(shù)名來代替注釋祟偷,增加程序的可讀性。

  • Category 擴(kuò)展不可覆蓋原有類的方法

  • 注意 block 循環(huán)強(qiáng)引用

  • 盡量不要用 KVO, 要用 NSNotification 或者 delegate 代替

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末打厘,一起剝皮案震驚了整個(gè)濱河市修肠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌户盯,老刑警劉巖嵌施,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異莽鸭,居然都是意外死亡吗伤,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門硫眨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來足淆,“玉大人,你說我怎么就攤上這事礁阁∏珊牛” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵姥闭,是天一觀的道長丹鸿。 經(jīng)常有香客問我,道長棚品,這世上最難降的妖魔是什么靠欢? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任弥姻,我火速辦了婚禮,結(jié)果婚禮上掺涛,老公的妹妹穿的比我還像新娘庭敦。我一直安慰自己,他們只是感情好薪缆,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布秧廉。 她就那樣靜靜地躺著,像睡著了一般拣帽。 火紅的嫁衣襯著肌膚如雪疼电。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天减拭,我揣著相機(jī)與錄音蔽豺,去河邊找鬼。 笑死拧粪,一個(gè)胖子當(dāng)著我的面吹牛修陡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播可霎,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼魄鸦,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了癣朗?” 一聲冷哼從身側(cè)響起拾因,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎旷余,沒想到半個(gè)月后绢记,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡正卧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年蠢熄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片穗酥。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡护赊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出砾跃,到底是詐尸還是另有隱情骏啰,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布抽高,位于F島的核電站判耕,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏翘骂。R本人自食惡果不足惜壁熄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一帚豪、第九天 我趴在偏房一處隱蔽的房頂上張望草丧。 院中可真熱鬧,春花似錦昌执、人聲如沸烛亦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岖赋。三九已至檬果,卻和暖如春唐断,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背栗涂。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國打工知牌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人斤程。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像菩混,于是被迫代替她去往敵國和親忿墅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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