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ù)
    • 常量
    • 變量
    • 通知和異常
  • 布爾值
  • 條件語句
  • 初始化方法
  • 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)度最多不超過100個(gè)字符

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

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

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

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

    如果某個(gè)函數(shù)或方法的實(shí)現(xiàn)代碼過長(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)接近或超過800行時(shí),就應(yīng)當(dāng)開始考慮分割實(shí)現(xiàn)文件了。

    最好不要出現(xiàn)代碼超過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,開啟行號(hào)提示。

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

    沒有空行,代碼過長(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ū)隔開來,方便閱讀,也方便查找是否忘記了對(duì)super的調(diào)用。

    - (void)viewWillDisappear:(BOOL)animated {
        [super viewWillDisappear:animated];
        
        //空一行,將super方法的調(diào)用和重載代碼區(qū)隔開來。
        [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)后面緊接著的代碼塊超過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與上一條分支語句的右括號(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)用中部分的代碼過長(zhǎng),造成內(nèi)嵌的block代碼縮進(jìn)過長(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ī)范

無論什么情況下,都要盡量堅(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è)類庫中,使用了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ù)過多超過一行時(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)該盡量讀起來像一句話。具體參見蘋果的方法名命名規(guī)范

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

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

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

    - (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;  //禁止
    
  • 類私有方法以下劃線開頭

    如:- (void)_startDownloadFiles;

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

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

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

    根據(jù)蘋果的建議,這種做法可能覆蓋掉父類的私有方法。
    但是目前還沒有遇到過這種情況,而且我們認(rèn)為此條約定帶來的好處遠(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語法

    //例如:
    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ò)誤問題。

    比如:

    static CGFloat const RWImageThumbnailHeight = 50.0;

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

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

    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í)例變量名以下劃線開頭,局部變量不能以下劃線開頭

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

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

    Objective-C中,變量名應(yīng)該盡量清楚的描述它的用途。這樣可以使別人立即明白代碼的意思,不要擔(dān)心這樣會(huì)導(dǎo)致代碼過長(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];
    
  • 指針符號(hào) "*" 靠近變量名字。(常量定義除外)

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

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

    //贊成的
    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ú)一無二的一段名稱] + Notification

    如:UIApplicationDidBecomeActiveNotification

  • 異常名字的命名規(guī)則:[前綴] + [獨(dú)一無二的一段名稱] + 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) {
        //...
    }
    
    //沒那么直觀的代碼
    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"開頭的別名。

    @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();
        }
    }
    

條件語句

  • 條件語句的語句體,即便只有一行,也不能省略花括弧

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

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

    Objective-C的代碼普遍比較長(zhǎng),如果再加上多層嵌套的條件語句,代碼縮進(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è)語句,最好用小括號(hào)括起來。如果直接是一個(gè)布爾值則無需括號(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的介紹參見NSHipster.com

CGRect函數(shù)

  • 訪問CGRect中的x、y、width或height元素時(shí),不直接訪問而是使用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ù)來進(jìn)行相關(guān)操作。

    什么叫標(biāo)準(zhǔ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ù)類型組織,更要以更加清晰的特征來區(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

最后貼張圖娛樂一下,雖然說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)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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