01.優(yōu)秀的Objective-C編碼風(fēng)格指南

@(〓〓 iOS-Objective-C精選)[Objective-C 文章精選]


目錄

  • 01.優(yōu)秀的Objective-C編碼風(fēng)格指南
  • 參考文檔
  • 目錄
  • 代碼結(jié)構(gòu)
  • 代碼格式化
  • 注釋
  • 命名規(guī)范
    • 類名/類別名/協(xié)議
    • 方法
    • 函數(shù)
    • 常量
    • 變量
    • 通知和異常
  • 布爾值
  • 條件語(yǔ)句
  • 初始化方法
  • CGRect函數(shù)
  • Xcode工程結(jié)構(gòu)
  • Just for fun

參考文檔

此編碼規(guī)范在制定的時(shí)候參考和借鑒了以下這些優(yōu)秀的Objective-C編碼風(fēng)格指南:

目錄

代碼結(jié)構(gòu)

實(shí)現(xiàn)文件中的代碼結(jié)構(gòu)闻牡,提倡以下約定:

  • #pragma mark -將函數(shù)或方法按功能進(jìn)行分組。

  • dealloc方法放到實(shí)現(xiàn)文件的最頂部塑娇。

    這樣是為了時(shí)刻提醒你要記得釋放相關(guān)資源澈侠。

  • delgate或協(xié)議相關(guān)方法放到一般內(nèi)容之后。

    #pragma mark - Lifecycle
    
    - (void)dealloc {}
    - (instancetype)init {}
    - (void)viewDidLoad {}
    - (void)viewWillAppear:(BOOL)animated {}
    - (void)didReceiveMemoryWarning {}
    
    #pragma mark - Custom Accessors
    
    - (void)setCustomProperty:(id)value {}
    - (id)customProperty {}
    
    #pragma mark - Protocol conformance
    #pragma mark - UITextFieldDelegate
    #pragma mark - UITableViewDataSource
    #pragma mark - UITableViewDelegate
    
    #pragma mark - NSCopying
    
    - (id)copyWithZone:(NSZone *)zone {}
    
    #pragma mark - NSObject
    
    - (NSString *)description {}
    

代碼格式化

  • 只用空格縮進(jìn)埋酬,1個(gè)TAB = 4個(gè)空格字符

    在XCode->Preferences->Text Editing->Indentation中進(jìn)行如下設(shè)置:

    1. Prefer indent using: 選擇 Spaces
    2. Tab key:選擇 Intents in leading whitespace
    3. 所有需要填寫空格數(shù)目的地方都設(shè)置成4個(gè)

    ps. 設(shè)置成4個(gè)哨啃,是因?yàn)閄code的默認(rèn)縮進(jìn)是4個(gè)空格。大量遺留代碼也都是采用的縮進(jìn)4個(gè)空格写妥。

  • 建議:每行代碼的長(zhǎng)度最多不超過(guò)100個(gè)字符

    為了防止代碼過(guò)長(zhǎng)拳球,也為了兼顧Macbook上的排版效果,將每行長(zhǎng)度限制成100個(gè)字符珍特。

    勾選XCode->Preferences->Text Editing->Editing祝峻,并將長(zhǎng)度設(shè)置成100個(gè)字符來(lái)打開(kāi)行寬指示。

    ps. Google倡導(dǎo)的每行80個(gè)字符有點(diǎn)少扎筒,會(huì)帶來(lái)更頻繁的換行莱找,因此增加到100個(gè)字符。

  • 建議:嘗試將單個(gè)函數(shù)或方法的實(shí)現(xiàn)代碼控制在30行內(nèi)

    如果某個(gè)函數(shù)或方法的實(shí)現(xiàn)代碼過(guò)長(zhǎng)嗜桌,可以考量下是否可以將代碼拆分成幾個(gè)小的擁有單一功能的方法奥溺。

    ps. 30行是在13寸macbook上XCode用14號(hào)字體時(shí),恰好可以讓一個(gè)函數(shù)的代碼做到整屏完全顯示的行數(shù)骨宠。

  • 建議:將單個(gè)實(shí)現(xiàn)文件里的代碼行數(shù)控制在500~600行內(nèi)

    為了簡(jiǎn)潔和便于閱讀浮定,建議將單個(gè)實(shí)現(xiàn)文件的代碼行數(shù)控制在500~600行以內(nèi)最好。

    當(dāng)接近或超過(guò)800行時(shí)层亿,就應(yīng)當(dāng)開(kāi)始考慮分割實(shí)現(xiàn)文件了桦卒。

    最好不要出現(xiàn)代碼超過(guò)1000行的實(shí)現(xiàn)文件。

    我們一般傾向于認(rèn)為單個(gè)文件代碼行數(shù)越長(zhǎng)匿又,代碼結(jié)構(gòu)就越不好方灾。而且,翻代碼翻的手軟啊琳省。

    可以使用Objective-C的Category特性將實(shí)現(xiàn)文件歸類分割成幾個(gè)相對(duì)輕量級(jí)的實(shí)現(xiàn)文件迎吵。

    可以勾選上XCode->Preferences->Text Editing->Editing中的Line numbers躲撰,開(kāi)啟行號(hào)提示。

  • 實(shí)現(xiàn)文件中击费,函數(shù)實(shí)現(xiàn)或方法實(shí)現(xiàn)之間必須至少有一行空行

    沒(méi)有空行拢蛋,代碼過(guò)長(zhǎng)后,全粘在一起蔫巩,很影響閱讀吏祸。

    //禁止的
    - (void)loadView {
        //load view...
    }
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        //Do Something...
    }
    
    
    //正確的
    - (void)loadView {
        //load view...
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        //Do Something...
    }
  • 重載父類方法時(shí)外冀,遇到必須調(diào)用父類方法時(shí)。調(diào)用super的代碼和重載的代碼之間留一行空行。

    這樣做是為了便于區(qū)分出對(duì)super的調(diào)用粹湃。
    通常在iOS SDK中诡必,有許多方法在重載的時(shí)候赊颠,都要求調(diào)用super侣监。有時(shí)候忘記調(diào)用super就會(huì)出現(xiàn)行為怪異的bug。
    因此這里要求將調(diào)用super的代碼區(qū)隔開(kāi)來(lái)歪沃,方便閱讀嗦锐,也方便查找是否忘記了對(duì)super的調(diào)用。

    - (void)viewWillDisappear:(BOOL)animated {
        [super viewWillDisappear:animated];
        
        //空一行沪曙,將super方法的調(diào)用和重載代碼區(qū)隔開(kāi)來(lái)奕污。
        [NSObject cancelPreviousPerformRequestsWithTarget:self];
    }
    
  • 實(shí)現(xiàn)文件中,函數(shù)體的左花括號(hào)不另起一行液走,和函數(shù)名同行碳默,并且和函數(shù)名之間保持1個(gè)空格

    此條是為了和XCode6.1模板生成的文件的代碼風(fēng)格保持一致。

    //贊成的
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    //不贊成的
    - (void)didReceiveMemoryWarning
    {
    
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
  • 其他地方(if/else/while/switch等)缘眶,左花括號(hào)不單獨(dú)另起一行嘱根。左花括號(hào)后面緊接著的代碼塊超過(guò)5行后,代碼塊和括號(hào)之間要有一行空行巷懈;代碼塊小于5行可以不空行

    此條是為了和XCode自動(dòng)代碼補(bǔ)全生成的代碼風(fēng)格保持一致儿子。

```objc
//贊成的
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    
    if (somethCondtion) {
    
        //DO Something. 
    }
}

//不贊成的
- (void)didReceiveMemoryWarning 
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    
    if (somethCondtion) 
    {
        //DO Something
    }
}
```
  • 建議: if/else中,else與上一條分支語(yǔ)句的右括號(hào)之間需要換行

    此條是為了防止else和上一個(gè)分支的代碼塊挨在一起砸喻,影響閱讀,所以建議要換行蒋譬。

    換行后割岛,也便于快速定位到else分支。

  //贊成的
  if (a > 0) {
  
      //Do Something
  } 
  else {
  
      //Do Something
  }
  
  //不贊成的
  if (a > 0) {
  
      //Do Something
  } else {
  
      //Do Something
  }
  • 如果需要手動(dòng)使用@synthesize@dynamic犯助,每行只能定義一個(gè)屬性

  • 方法調(diào)用中癣漆,如果block參數(shù)需要換行時(shí),block結(jié)尾的花括弧要和聲明block那一行的第一個(gè)字符對(duì)齊

    [operation setCompletionBlock:^{
        [self.delegate newDataAvailable];
    }];
    
  • 如果方法調(diào)用中部分的代碼過(guò)長(zhǎng)剂买,造成內(nèi)嵌的block代碼縮進(jìn)過(guò)長(zhǎng)惠爽,可以適當(dāng)?shù)脑黾邮謩?dòng)換行癌蓖,以減少代碼縮進(jìn)

    //如以下代碼在loadWindowWithCompletionBlock前加了手動(dòng)換行,是被提倡的:
    [[SessionService sharedService]
        loadWindowWithCompletionBlock:^(SessionWindow *window) {
        
            if (window) {
                [self windowDidLoad:window];
            } 
            else {
                [self errorLoadingWindow];
            }
    }];
    

注釋

  • 注釋應(yīng)該盡量保持簡(jiǎn)潔婚肆,代碼應(yīng)該盡量達(dá)到能自我解釋的程度

    當(dāng)然用于生成文檔的注釋除外租副,用于生成文檔的注釋要盡量詳細(xì),特別是你的接口可能有副作用的時(shí)候较性,要注釋清楚用僧。

  • 注釋必須和代碼保持同步。不要出現(xiàn)代碼修改了赞咙,注釋不更新的情況

  • 對(duì)函數(shù)或API接口的注釋责循,都采用Javadoc風(fēng)格規(guī)范

    因?yàn)閄Code5支持直接將Javadoc風(fēng)格的注釋生成文檔。

    也有用于添加Javadoc風(fēng)格注釋的XCode插件:VVDocumenter-Xcode

命名規(guī)范

無(wú)論什么情況下攀操,都要盡量堅(jiān)持蘋果的命名規(guī)范院仿,特別是涉及到內(nèi)存管理規(guī)則時(shí)

這里的"內(nèi)存管理規(guī)則",強(qiáng)調(diào)的是底層Core Foundation框架中速和,名字帶Create或Copy的函數(shù)歹垫,返回的對(duì)象,你要負(fù)責(zé)它的釋放健芭。

類名/類別名/協(xié)議

  • 類名县钥、類別名字及協(xié)議名字,都采用大駝峰式命名規(guī)則

  • 文件名要能反映出它所包含的類的名稱

    如:NSString.h 和 NSString.m 包含了NSString類的定義和實(shí)現(xiàn)

  • Category的文件名要包含它所擴(kuò)展的那個(gè)類的名稱慈迈,并且類別名稱要盡量能夠描述它的功能

    UIImage+Resize.h 或 UIImage+TintColor.h

  • 在面向特定應(yīng)用的代碼中若贮,類名盡量避免使用前綴,每個(gè)類都使用相同的前綴會(huì)影響可讀性

    面向特定應(yīng)用的代碼痒留,指那些只會(huì)在一個(gè)項(xiàng)目中使用的代碼谴麦,不會(huì)被用于其他項(xiàng)目中的代碼。

  • 在面向多應(yīng)用的代碼中伸头,類名要使用前綴匾效,防止命名沖突

    面向多應(yīng)用的代碼,指那些會(huì)被多個(gè)項(xiàng)目共同使用的代碼恤磷。

    比如CRKit這個(gè)類庫(kù)中面哼,使用了CR前綴。

  • 建議:前綴至少使用三個(gè)字母

    此條是為了減少命名沖突扫步。但鑒于目前流行前綴大多都是兩個(gè)字母魔策,所以此條不做強(qiáng)制要求

  • 協(xié)議聲明或定義中,類型標(biāo)識(shí)符河胎、協(xié)議名稱闯袒、尖括號(hào)之間不留空格

    @interface MyProtocoledClass : NSObject<NSWindowDelegate> 
    {
        @private
        id<MyFancyDelegate> _delegate;
    }
    
    - (void)setDelegate:(id<MyFancyDelegate>)aDelegate;
    @end
    

方法

  • 方法名和參數(shù)名都采用小駝峰式命名規(guī)則。

    如:- (BOOL)isFileExistedAtPath:(NSString *)filePath;

  • 方法聲明中,-/+和返回值類型之間要空1個(gè)空格政敢,方法名和參數(shù)類型之間以及參數(shù)類型和參數(shù)名之間不留空格

    - (void)invokeWithTarget:(id)target; //正確
    - (void)invokeWithTarget: (id)target; //錯(cuò)誤
    - (void)invokeWithTarget:(id) target; //錯(cuò)誤
    - (void)invokeWithTarget: (id) target; //錯(cuò)誤
    
  • 方法聲明中其徙,參數(shù)過(guò)多超過(guò)一行時(shí),可以增加手動(dòng)換行喷户,使每個(gè)參數(shù)占用一行唾那,以冒號(hào)對(duì)齊

    - (void)doSomethingWith:(GTMFoo *)theFoo
                       rect:(NSRect)theRect
                   interval:(float)theInterval;
    
  • 方法名第一段比其他部分短時(shí),每個(gè)參數(shù)占用一行摩骨,每行至少縮進(jìn)4個(gè)空格通贞,盡量保持參數(shù)以冒號(hào)對(duì)齊

    同時(shí)選中多行代碼,用快捷鍵"command+["或"command+]"可以減少或增加縮進(jìn)恼五。

    - (void)short:(GTMFoo *)theFoo
                  longKeyword:(NSRect)theRect
            evenLongerKeyword:(float)theInterval
                        error:(NSError **)theError; 
    
  • 方法名和參數(shù)名應(yīng)該盡量讀起來(lái)像一句話昌罩。具體參見(jiàn)蘋果的方法名命名規(guī)范

    如:convertPoint:fromRect: 或者 replaceCharactersInRange:withString:

  • 當(dāng)各個(gè)參數(shù)是接收者的某個(gè)屬性時(shí),方法名中不要用"and"來(lái)連接

    //贊成的
    - (int)runModalForDirectory:(NSString *)path file:(NSString *) name types:(NSArray *)fileTypes;
    
    //不贊成的
    - (int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileTypes;
    
  • 如果方法名描述了兩種不同的動(dòng)作灾馒,要使用"and"來(lái)連接

    - (BOOL)openFile:(NSString *)fullPath withApplication:(NSString *)appName andDeactivate:(BOOL)flag;
    
  • getter方法的方法名應(yīng)該和變量名字相同茎用,不允許使用"get"前綴

    本規(guī)則僅適用于Objective-C,C++使用C++的相關(guān)規(guī)范

    - (id)delegate;     // 正確
    - (id)getDelegate;  //禁止
    
  • 類私有方法以下劃線開(kāi)頭

    如:- (void)_startDownloadFiles;

    Objective-C里面沒(méi)有真正嚴(yán)格意義上私有方法睬罗。這里所說(shuō)的"私有方法"指那些不需要公開(kāi)的轨功、只會(huì)在實(shí)現(xiàn)文件中使用的方法。

    這樣做的好處是容达,可以直觀的快速區(qū)別實(shí)現(xiàn)文件中的私有方法和公有方法古涧。

    這樣做會(huì)很便于重構(gòu)。如果某個(gè)方法廢棄了花盐,需要移除的時(shí)候羡滑,發(fā)現(xiàn)它是以下劃線開(kāi)頭的,那么就可以確定這個(gè)方法是私有的算芯,只會(huì)在這個(gè)實(shí)現(xiàn)文件中被用到柒昏。那么直接在該實(shí)現(xiàn)文件搜索這個(gè)方法的名字,然后清理掉搜索到的地方就可以了熙揍。不必再在整個(gè)項(xiàng)目中查找是否沒(méi)有清理干凈职祷。

    根據(jù)蘋果的建議,這種做法可能覆蓋掉父類的私有方法届囚。
    但是目前還沒(méi)有遇到過(guò)這種情況有梆,而且我們認(rèn)為此條約定帶來(lái)的好處遠(yuǎn)遠(yuǎn)大于它潛在的危險(xiǎn),因此仍然推行這條約定意系。

函數(shù)

函數(shù)指純C函數(shù)淳梦,這里提倡與蘋果風(fēng)格類似的約定。

  • 函數(shù)名采用大駝峰式命名方式昔字,參數(shù)名采用小駝峰式命名方式

  • 如果函數(shù)和某個(gè)特定類型相關(guān),那么函數(shù)名前綴要和類型前綴一樣

    CGRectMake()CGContextCreate()

常量

  • 創(chuàng)建NSString, NSDictionary, NSArray, 以及NSNumber等常量時(shí)作郭,使用Literals語(yǔ)法

    //例如:
    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 *ZIPCode = [NSNumber numberWithInteger:10018];
    
  • 定義枚舉常量時(shí)陨囊,使用NS_ENUM或NS_OPTIONS

    NS_ENUM和NS_OPTIONS都提供了類型檢查

    //例如:
    typedef NS_ENUM(NSUInteger, PPNavBarButtonColor) {
        PPNavBarButtonColorBlack,
        PPNavBarButtonColorGreen,
        PPNavBarButtonColorDefault = PPNavBarButtonColorBlack
    };
    
    typedef NS_OPTIONS(NSUInteger, PSTCollectionViewScrollPosition) {
        PSTCollectionViewScrollPositionNone                 = 0,
        
        PSTCollectionViewScrollPositionTop                  = 1 << 0,
        PSTCollectionViewScrollPositionCenteredVertically   = 1 << 1,
        PSTCollectionViewScrollPositionBottom               = 1 << 2,
        
        PSTCollectionViewScrollPositionLeft                 = 1 << 3,
        PSTCollectionViewScrollPositionCenteredHorizontally = 1 << 4,
        PSTCollectionViewScrollPositionRight                = 1 << 5
    };
    
  • 定義常量時(shí),除非明確的需要將常量當(dāng)成宏使用夹攒,否則優(yōu)先使用const蜘醋,而非#define

  • 只在某一個(gè)特定文件里面使用的常量,用static

    static關(guān)鍵字保證變量只有文件作用域咏尝,可以避免變量名重名造成的鏈接錯(cuò)誤問(wèn)題压语。

    比如:

    static CGFloat const RWImageThumbnailHeight = 50.0;

  • 常量名以小寫k開(kāi)頭,采用首字母大寫的方式來(lái)分割單詞

    //例如:
    const int kNumberOfFiles = 12;
    NSString *const kUserKey = @"kUserKey";
    enum DisplayTinge {
        kDisplayTingeGreen = 1,
        kDisplayTingeBlue = 2
    };
    
  • 和特定類型相關(guān)的枚舉常量使用類名作為前綴编检,而不用小寫k開(kāi)頭胎食。

    typedef NS_OPTIONS(NSUInteger, UICollectionViewScrollPosition) {
        UICollectionViewScrollPositionNone                 = 0,
        UICollectionViewScrollPositionTop                  = 1 << 0,
        UICollectionViewScrollPositionCenteredVertically   = 1 << 1,
        UICollectionViewScrollPositionBottom               = 1 << 2,
        UICollectionViewScrollPositionLeft                 = 1 << 3,
        UICollectionViewScrollPositionCenteredHorizontally = 1 << 4,
        UICollectionViewScrollPositionRight                = 1 << 5
    };
    

變量

  • 屬性名和變量名都采用小駝峰式命名規(guī)則

  • 實(shí)例變量名以下劃線開(kāi)頭,局部變量不能以下劃線開(kāi)頭

  • 禁止使用匈牙利標(biāo)記法或含糊不清的縮寫單詞來(lái)命名變量

    for循環(huán)中的i允懂、j厕怜、k這種情況例外。

    Objective-C中蕾总,變量名應(yīng)該盡量清楚的描述它的用途粥航。這樣可以使別人立即明白代碼的意思,不要擔(dān)心這樣會(huì)導(dǎo)致代碼過(guò)長(zhǎng)生百。

    //以下這些都是錯(cuò)誤的命名規(guī)范
    int w;
    int nerr;
    int nCompConns;
    tix = [[NSMutableArray alloc] init];
    obj = [someObject object];
    p = [network port];
    
    //以下這些才是贊成的命名規(guī)范
    int numErrors;
    int numCompletedConnections;
    tickets = [[NSMutableArray alloc] init];
    userInfo = [someObject object];
    port = [network port];
    
  • 指針?lè)?hào) "*" 靠近變量名字递雀。(常量定義除外)

    NSString *varName; //贊成的
    
    NSString* varName; //不贊成的
    
  • 使用property時(shí),優(yōu)先使用點(diǎn)語(yǔ)法

    使用點(diǎn)語(yǔ)法會(huì)讓代碼簡(jiǎn)潔蚀浆。但對(duì)于其他情況缀程,都應(yīng)該使用方括號(hào)語(yǔ)法。

    //贊成的
    NSInteger arrayCount = [self.array count];
    view.backgroundColor = [UIColor orangeColor];
    [UIApplication sharedApplication].delegate;
    
    //不贊成的
    NSInteger arrayCount = self.array.count;
    [view setBackgroundColor:[UIColor orangeColor]];
    UIApplication.sharedApplication.delegate;
    

通知和異常

  • 通知名字的命名規(guī)則:[相關(guān)聯(lián)的類名字] + [Did | Will] + [獨(dú)一無(wú)二的一段名稱] + Notification

    如:UIApplicationDidBecomeActiveNotification

  • 異常名字的命名規(guī)則:[前綴] + [獨(dú)一無(wú)二的一段名稱] + Exception

    如:NSColorListIOException

布爾值

  • Objective-C的布爾值只使用YESNO

  • truefalse只能用于CoreFoundation蜡坊,C或C++的代碼中

  • 禁止將某個(gè)值或表達(dá)式的結(jié)果與YES進(jìn)行比較

    因?yàn)锽OOL被定義成signed char杠输。這意味著除了YES(1)和NO(0)以外,它還可能是其他值秕衙。

    因此C或C++中的非0為真并不一定就是YES

    //以下都是被禁止的
    - (BOOL)isBold {
        return [self fontTraits] & NSFontBoldTrait;
    }
    
    - (BOOL)isValid {
        return [self stringValue];
    }
    
    if ([self isBold] == YES) {
        //...
    }
    
    
    //以下才是贊成的方式
    - (BOOL)isBold {
        return ([self fontTraits] & NSFontBoldTrait) ? YES : NO;
    }
    
    - (BOOL)isValid {
        return [self stringValue] != nil;
    }
    
    - (BOOL)isEnabled {
        return [self isValid] && [self isBold];
    }
    
    if ([self isBold]) {
        //...
    }
  • 雖然nil會(huì)被直接解釋成NO蠢甲,但還是建議在條件判斷時(shí)保持與nil的比較,因?yàn)檫@樣代碼更直觀据忘。

    //比如鹦牛,更直觀的代碼
    if (someObject != nil) {
        //...
    }
    
    //沒(méi)那么直觀的代碼
    if (!someObject) {
        //...
    }
    
  • 在C或C++代碼中,要注意NULL指針的檢測(cè)勇吊。

    向一個(gè)nil的Objective-C對(duì)象發(fā)送消息不會(huì)導(dǎo)致崩潰曼追。但由于Objective-C運(yùn)行時(shí)不會(huì)處理給NULL指針的情況,所以為了避免崩潰汉规,需要自行處理對(duì)于C/C++的NULL指針的檢測(cè)礼殊。

  • 如果某個(gè)BOOL類型的property的名字是一個(gè)形容詞驹吮,建議為getter方法加上一個(gè)"is"開(kāi)頭的別名。

    @property (assign, getter = isEditable) BOOL editable;
    
  • 在方法實(shí)現(xiàn)中晶伦,如果有block參數(shù)碟狞,要注意檢測(cè)block參數(shù)為nil的情況。

    - (void)exitWithCompletion:(void(^)(void))completion {
        // 錯(cuò)誤婚陪。 如果外部調(diào)用此方法時(shí)completion傳入nil族沃,此處會(huì)發(fā)生EXC_BAD_ACCESS
        completion();
        
        // 正確。如果completion不存在則不調(diào)用泌参。
        if (completion) {
            completion();
        }
    }
    

條件語(yǔ)句

  • 條件語(yǔ)句的語(yǔ)句體脆淹,即便只有一行,也不能省略花括弧

    這樣可以減少失誤沽一。比如你在if語(yǔ)句體中增加第二行語(yǔ)句的時(shí)候盖溺,就可能會(huì)因?yàn)闆](méi)有花括號(hào)而導(dǎo)致新增的第二行語(yǔ)句沒(méi)有被包含在if語(yǔ)句體中。另外锯玛,這里還提到了其他的一些危險(xiǎn)情況咐柜。

    //贊成的
    if (error == nil) {
      return success;
    }
    
    //不贊成的
    if (error == nil)
      return success;
      
    //或
    if (error == nil) return success;
    
  • 多層嵌套的條件語(yǔ)句,優(yōu)先考慮條件不成立可以立即跳出的情況

    Objective-C的代碼普遍比較長(zhǎng)攘残,如果再加上多層嵌套的條件語(yǔ)句拙友,代碼縮進(jìn)會(huì)增多,代碼會(huì)變得更長(zhǎng)歼郭,會(huì)影響可讀性遗契。比如,下面這種情況病曾,換成優(yōu)先考慮可以跳出的情況牍蜂,可以有效的減少代碼縮進(jìn)長(zhǎng)度:

    //一般流程
    if (a) {
    
        if (b) {
        
            if (c) {
            
                //do something
            } 
        } 
    
    } 
    
    
    //優(yōu)先考慮可以跳出的流程
    if (!a) {
        return;
    }
    
    if (!b) {
        return;
    }
    
    if (!c) {
        return;
    }
    
    //do something
  • 三目運(yùn)算只有在能增加代碼清晰度和整潔度的時(shí)候才推薦使用

    三目運(yùn)算符(?:),如果不能增加代碼整潔度和清晰度泰涂,使用時(shí)就要謹(jǐn)慎鲫竞。特別是,嵌套使用多個(gè)三目運(yùn)算逼蒙,這種要盡量避免从绘。因?yàn)樗鼤?huì)使代碼更難閱讀。

    另外是牢,三目運(yùn)算符中的條件判斷是一個(gè)語(yǔ)句僵井,最好用小括號(hào)括起來(lái)。如果直接是一個(gè)布爾值則無(wú)需括號(hào)驳棱。例如:

    //贊成的
    NSInteger value = 5;
    result = (value != 0) ? x : y;
    
    BOOL isHorizontal = YES;
    result = isHorizontal ? x : y;
    
    //不贊成的
    result = a > b ? x = c > d ? c : d : y;
    

初始化方法

  • 初始化方法的返回類型用instancetype

    關(guān)于instancetype的介紹參見(jiàn)NSHipster.com批什。

CGRect函數(shù)

  • 訪問(wèn)CGRect中的x、y社搅、width或height元素時(shí)驻债,不直接訪問(wèn)而是使用CGGeometry相關(guān)函數(shù)

    CGGeometry里面的函數(shù)乳规,會(huì)對(duì)CGRect參數(shù)進(jìn)行隱式的標(biāo)準(zhǔn)化處理,然后再計(jì)算結(jié)果合呐。因此驯妄,你應(yīng)該避免直接讀取或重寫CGRect數(shù)據(jù)結(jié)構(gòu)里面的值,而要使用這些函數(shù)來(lái)進(jìn)行相關(guān)操作合砂。

    什么叫標(biāo)準(zhǔn)化處理,參見(jiàn)CGGeometry Reference的Overview章節(jié)源织。

    //贊成的
    CGRect frame = self.view.frame;
    
    CGFloat x = CGRectGetMinX(frame);
    CGFloat y = CGRectGetMinY(frame);
    CGFloat width = CGRectGetWidth(frame);
    CGFloat height = CGRectGetHeight(frame);
    CGRect frame = CGRectMake(0.0, 0.0, width, height);
    
    //不贊成的
    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;
    CGRect frame = (CGRect){ .origin = CGPointZero, .size = frame.size };
    

Xcode工程結(jié)構(gòu)

  • 實(shí)體文件應(yīng)該和XCode工程文件保持同步翩伪,防止出現(xiàn)文件不一致

    任何手動(dòng)創(chuàng)建的XCode Group都應(yīng)該在文件系統(tǒng)有一個(gè)對(duì)應(yīng)的文件夾。代碼不僅要根據(jù)類型組織谈息,更要以更加清晰的特征來(lái)區(qū)分歸類缘屹。

  • 建議:在可能的情況下,始終要勾選在Build設(shè)置選項(xiàng)中”Treat Warnings as Errors(將告警視為錯(cuò)誤)“選項(xiàng)侠仇。同時(shí)盡可能多的暴露更多的additional warnings(附加告警)轻姿。如果要忽略某類特定Warning(告警),請(qǐng)使用Clang's pragma feature逻炊。

    此條不做強(qiáng)制要求互亮,但是"將警告視為錯(cuò)誤"是你應(yīng)當(dāng)要有的態(tài)度。

Just for fun

最后貼張圖娛樂(lè)一下余素,雖然說(shuō)Objective-C中長(zhǎng)名是美德豹休,但是什么東西還是要有個(gè)度。有人寫了個(gè)腳本統(tǒng)計(jì)Cocoa Framework中各種最長(zhǎng)的命名桨吊,結(jié)果發(fā)現(xiàn)低估了蘋果程序員的造句能力威根。Mac平臺(tái)最長(zhǎng)的常量名96個(gè)字符,最長(zhǎng)的方法名150個(gè)字符视乐,C函數(shù)名都能到68個(gè)字符洛搀! -_-# 泥煤,自從學(xué)會(huì)了Objective-C佑淀,媽媽再也不用擔(dān)心我的造句能力了留美。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市渣聚,隨后出現(xiàn)的幾起案子独榴,更是在濱河造成了極大的恐慌,老刑警劉巖奕枝,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棺榔,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡隘道,警方通過(guò)查閱死者的電腦和手機(jī)症歇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門郎笆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人忘晤,你說(shuō)我怎么就攤上這事宛蚓。” “怎么了设塔?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵凄吏,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我闰蛔,道長(zhǎng)痕钢,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任序六,我火速辦了婚禮任连,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘例诀。我一直安慰自己随抠,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布繁涂。 她就那樣靜靜地躺著拱她,像睡著了一般。 火紅的嫁衣襯著肌膚如雪爆土。 梳的紋絲不亂的頭發(fā)上椭懊,一...
    開(kāi)封第一講書(shū)人閱讀 49,749評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音步势,去河邊找鬼氧猬。 笑死,一個(gè)胖子當(dāng)著我的面吹牛坏瘩,可吹牛的內(nèi)容都是我干的盅抚。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼倔矾,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼妄均!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起哪自,我...
    開(kāi)封第一講書(shū)人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤丰包,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后壤巷,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體邑彪,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年胧华,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了寄症。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宙彪。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖有巧,靈堂內(nèi)的尸體忽然破棺而出释漆,到底是詐尸還是另有隱情,我是刑警寧澤篮迎,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布男图,位于F島的核電站,受9級(jí)特大地震影響甜橱,放射性物質(zhì)發(fā)生泄漏享言。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一渗鬼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧荧琼,春花似錦譬胎、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至脐恩,卻和暖如春镐侯,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背驶冒。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工苟翻, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人骗污。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓崇猫,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親需忿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子诅炉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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