Objective-C 編程規(guī)范

命名規(guī)范

1.【強(qiáng)制】 代碼中的命名均不能以下劃線或美元符號(hào)開始,也不能以下劃線或美元符號(hào)結(jié)束。

反例: _name / __name / $Object / name_ / name$ / Object$

2.【強(qiáng)制】 代碼中的命名嚴(yán)禁使用拼音與英文混合的方式,更不允許直接使用中文的方式。

說明:正確的英文拼寫和語法可以讓閱讀者易于理解,避免歧義。注意,即使純拼音命名方式 也要避免采用。

反例:DaZhePromotion [打折] / getPingfenByName() [評(píng)分] / int 某變量 = 3

正例:alibaba / taobao / youku / hangzhou 等國際通用的名稱,可視同英文。

3.【強(qiáng)制】類名使用 UpperCamelCase 風(fēng)格,必須遵從駝峰形式,但領(lǐng)域模型相關(guān)的命名除外,比如 UserDAO

正例:MarcoPolo / UserDO / XmlService / TcpUdpDeal / TaPromotion

反例:macroPolo / UserDo / XMLService / TCPUDPDeal / TAPromotion

4.【強(qiáng)制】方法名、參數(shù)名、成員變量、局部變量都統(tǒng)一使用 lowerCamelCase 風(fēng)格,必須遵從 駝峰形式。

正例:localValue / getHttpMessage / inputUserId

5.【強(qiáng)制】常量命名全部大寫,單詞間用下劃線隔開,力求語義表達(dá)完整清楚,不要嫌名字長。

正例:MAX_STOCK_COUNT

反例:MAX_COUNT

6.【強(qiáng)制】異常類命名使用 Exception 結(jié)尾;測試類命名以它要測試的類的名稱開始,以 Test 結(jié)尾。

7.【強(qiáng)制】杜絕完全不規(guī)范的縮寫,避免望文不知義。

8.【強(qiáng)制】文件名和類名同名。

9.【推薦】如果使用到了設(shè)計(jì)模式,建議在類名中體現(xiàn)出具體模式。

說明:將設(shè)計(jì)模式體現(xiàn)在名字中,有利于閱讀者快速理解架構(gòu)設(shè)計(jì)思想。

10.【推薦】類名應(yīng)加上三個(gè)大寫字母作為前綴(兩個(gè)字母的為 Apple 的類保留)。

11.【強(qiáng)制】特殊類的命名,如果是視圖控制器的子類應(yīng)添加后綴“ViewController”或者“Controller”,如果是視圖的子類應(yīng)添加后綴“View”,如果是按鈕的子類應(yīng)添加后綴“Button”。

12.【強(qiáng)制】分類 Category 命名,與類命名相同,此外需添加要擴(kuò)展的類名和“+”

13.【強(qiáng)制】協(xié)議(委托)命名,與類命名相同,此外需添加“Delegate”后綴

14.【推薦】方法返回值為Boolean 類型,應(yīng)加 is 前綴。如果某方法返回非屬性的 Boolean 值,那么應(yīng)該根據(jù)其功能,選用 has 或 is 當(dāng)前綴。

- (BOOL)isEqualToString:(NSString *)aString; 
- (BOOL)hasPrefix:(NSString *)aString;

15.【推薦】方法名不要使用 new 作為前綴

16.【推薦】不要使用 and 來連接用屬性作參數(shù)的關(guān)鍵字

17.【推薦】方法連接多個(gè)參數(shù)命名時(shí),適當(dāng)使用合適的介詞。比如 in for at by of with

//清晰
insertObject:atIndex:

//不清晰,insert的對(duì)象類型和at的位置屬性沒有說明
insert:at:

//清晰
removeObjectAtIndex:

//不清晰,remove的對(duì)象類型沒有說明,參數(shù)的作用沒有說明
remove:

18.【推薦】定義成員變量,添加下劃線前綴。但不推薦使用成員變量,直接使用屬性。

19.【強(qiáng)制】資源圖片命名,圖片應(yīng)該與類文件一樣,按模塊分組放置,縮略前綴可用如下例子

icon btn bg line logo pic img

常量定義

1.【強(qiáng)制】不允許出現(xiàn)任何魔法值(即未經(jīng)定義的常量)直接出現(xiàn)在代碼中。

2.【推薦】不要使用一個(gè)常量類維護(hù)所有常量,應(yīng)該按常量功能進(jìn)行歸類,分開維護(hù)。

如:緩存相關(guān)的常量放在類:CacheConsts下;系統(tǒng)配置相關(guān)的常量放在類:ConfigConsts下。

說明:大而全的常量類,非得使用查找功能才能定位到修改的常量,不利于理解和維護(hù)。

3.【強(qiáng)制】常量使用小寫k開頭的駝峰法。

static const NSTimeInterval kAnimationDuration = 0.3;

4.【強(qiáng)制】若常量作用域超出編譯單元,在類外可見時(shí),

.h
extern NSString *const EOCStringConstant;

.m
NSString *const EOCStringConstant = @"aaa";

5.【強(qiáng)制】全局常量(通知或者關(guān)鍵字等)盡量用const來定義,而不是宏。因?yàn)槿绻褂煤甓x, 宏可能被重定義,引用不同的文件可能會(huì)導(dǎo)致宏的不同。

格式規(guī)范

1.【強(qiáng)制】大括號(hào)的使用約定。如果是大括號(hào)內(nèi)為空,則簡潔地寫成{}即可,不需要換行;如果 是非空代碼塊則:

    1. 左大括號(hào)前不換行。
    1. 左大括號(hào)后換行。
    1. 右大括號(hào)前換行。
    1. 右大括號(hào)后還有else等代碼則不換行;表示終止右大括號(hào)后必須換行。

2.【強(qiáng)制】 左括號(hào)和后一個(gè)字符之間不出現(xiàn)空格;同樣,右括號(hào)和前一個(gè)字符之間也不出現(xiàn)空格。

3.【強(qiáng)制】if/for/while/switch/do 等保留字與左右括號(hào)之間都必須加空格。

4.【強(qiáng)制】任何運(yùn)算符左右必須加一個(gè)空格。

說明:運(yùn)算符包括賦值運(yùn)算符=、邏輯運(yùn)算符&&、加減乘除符號(hào)、三目運(yùn)算符等。

5.【強(qiáng)制】縮進(jìn)采用 4 個(gè)空格,禁止使用 tab 字符。

- (void)method {
    // 縮進(jìn) 4 個(gè)空格
    NSString *say = @"hello";
    // 運(yùn)算符的左右必須有一個(gè)空格
    NSInteger flag = 0;
    // 關(guān)鍵詞 if 與括號(hào)之間必須有一個(gè)空格,括號(hào)內(nèi)的 f 與左括號(hào),0 與右括號(hào)不需要空格
    if (flag == 0) {
        NSLog(@"%@", say);
    }
    
    // 左大括號(hào)前不加空格且不換行,左大括號(hào)后換行
    if (flag == 1) {
        NSLog(@"world");
        // 右大括號(hào)前換行,右大括號(hào)后有 else,不用換行
    } else {
        NSLog(@"ok");
        // 在右大括號(hào)后直接結(jié)束,則必須換行
    }
}

6.【強(qiáng)制】單行字符數(shù)限制不超過 120 個(gè),超出需要換行,按照:來對(duì)齊分行顯示

-(id)initWithModel:(IPCModle)model
       ConnectType:(IPCConnectType)connectType
        Resolution:(IPCResolution)resolution
          AuthName:(NSString *)authName
          Password:(NSString *)password
               MAC:(NSString *)mac
              AzIp:(NSString *)az_ip
             AzDns:(NSString *)az_dns
             Token:(NSString *)token
             Email:(NSString *)email
          Delegate:(id<IPCConnectHandlerDelegate>)delegate;

在分行時(shí),如果第一段名稱過短,后續(xù)名稱可以以Tab的長度(4個(gè)空格)為單位進(jìn)行縮進(jìn):

- (void)short:(GTMFoo *)theFoo
        longKeyword:(NSRect)theRect
  evenLongerKeyword:(float)theInterval
              error:(NSError **)theError {
    ...
}

函數(shù)的調(diào)用同理。

//寫在一行
[myObject doFooWith:arg1 name:arg2 error:arg3];

//分行寫,按照':'對(duì)齊
[myObject doFooWith:arg1
               name:arg2
              error:arg3];

//第一段名稱過短的話后續(xù)可以進(jìn)行縮進(jìn)
[myObj short:arg1
          longKeyword:arg2
    evenLongerKeyword:arg3
                error:arg4];

7.【強(qiáng)制】多個(gè)參數(shù)逗號(hào)后邊必須加空格。

正例:

NSLog(@"%@-%@-%@-%@", a, b, c, d);

8.【推薦】沒有必要增加若干空格來使某一行的字符與上一行的相應(yīng)字符對(duì)齊。

說明:在變量比較多的 情況下,是一種累贅的事情。

@interface HOECoupon : NSObject

@property (nonatomic, assign) NSInteger couponId;
@property (nonatomic, copy) NSString *startTime;
@property (nonatomic, copy) NSString *endTime;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subTitle;
@property (nonatomic, assign) NSInteger state;
@property (nonatomic, assign) NSInteger canUse;
@property (nonatomic, assign) CGFloat price;
@property (nonatomic, copy) NSString *stateDesc;
@property (nonatomic, copy) NSString *reason;

@end

9.【推薦】方法體內(nèi)的執(zhí)行語句組、變量的定義語句組、不同的業(yè)務(wù)邏輯之間或者不同的語義之間插入一個(gè)空行。相同業(yè)務(wù)邏輯和語義之間不需要插入空行。

說明:沒有必要插入多行空格進(jìn)行隔開。

10.【推薦】.m實(shí)現(xiàn)類中推薦的代碼結(jié)構(gòu)如下

#pragma mark - lifecycle
- (void)dealloc
- (void)viewDidLoad
- (void)viewWillAppear:(BOOL)animated
...
#pragma mark - UITableViewDataSource & UITableViewDelegate
...
#pragma mark - Event handlers
- (void)didTapLikeButton:
...
#pragma mark - public methods
...
#pragma mark - private methods
- (void)setupTableView
- (void)setupNotification
...
#pragma mark - getters & setters
...

11.【推薦】頭文件引用的順序

//  controllers
#import "OrcaAddFriendFromContactsViewController.h"
...
// views
...
// consts
...
// utils
...
// others

12.【推薦】方法的格式,在-和(void)之間應(yīng)該有一個(gè)空格

- (void)writeVideoFrameWithData:(NSData *)frameData timeStamp:(int)timeStamp {
    ...
}

面向?qū)ο笠?guī)范

1.【強(qiáng)制】避免通過一個(gè)類的對(duì)象引用訪問此類的靜態(tài)變量或靜態(tài)方法,無謂增加編譯器解析成本,直接用類名來訪問即可。

2.【強(qiáng)制】不能使用過時(shí)的類或方法。

3.【強(qiáng)制】推薦使用 NS_ENUM ,而不是 enum

typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
    UIViewAnimationTransitionNone,
    UIViewAnimationTransitionFlipFromLeft,
    UIViewAnimationTransitionFlipFromRight,
    UIViewAnimationTransitionCurlUp,
    UIViewAnimationTransitionCurlDown,
};

4.【推薦】盡量使用字面量來初始化

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

5.【推薦】建議定義屬性的時(shí)候把所有的參數(shù)寫全, 尤其是如果想定義成只讀的(防止外面修改)那一定要加上readonly, 這也是代碼安全性的一個(gè)習(xí)慣。

@property (nonatomic, readwrite, copy) NSString *name;

6.【強(qiáng)制】方法參數(shù)過多,需要進(jìn)行重構(gòu)

正例:

- (void)registerUser(User *user) {
     // to do...
}

反例:

- (void)registerUserName:(NSString *)userName
                password:(NSString *)password 
                   email:(NSString *)email {
     // to do...
}

7.【強(qiáng)制】不推薦使用成員變量,直接使用屬性。

8.【推薦】setter 方法中,參數(shù)名稱與類成員變量名稱一致,self.成員名 = 參數(shù)名。在getter/setter 方法中,盡量不要增加業(yè)務(wù)邏輯,增加排查問題的難度。

9.【推薦】對(duì)于簡單對(duì)象,推薦在getter方法中延遲加載屬性,如果創(chuàng)建復(fù)雜對(duì)象,那么對(duì)象的創(chuàng)建最好放到類的初始化時(shí),而不是延遲加載。

10.【推薦】協(xié)議,在書寫協(xié)議的時(shí)候注意用<>括起來的協(xié)議和類型名之間是沒有空格的

@interface MyProtocoledClass : NSObject<NSWindowDelegate> {
}

- (void)setDelegate:(id<MyFancyDelegate>)aDelegate;
@end

11.【推薦】閉包Block規(guī)則

  • 較短的block可以寫在一行內(nèi)。
  • 如果分行顯示的話,block的右括號(hào)}應(yīng)該和調(diào)用block那行代碼的第一個(gè)非空字符對(duì)齊。
  • block內(nèi)的代碼采用4個(gè)空格的縮進(jìn)。
  • 如果block過于龐大,應(yīng)該單獨(dú)聲明成一個(gè)變量來使用。
  • ^ 和(之間,^ 和{之間都沒有空格,參數(shù)列表的右括號(hào))和{之間有一個(gè)空格。
//較短的block寫在一行內(nèi)
[operation setCompletionBlock:^{ [self onOperationDone]; }];

//分行書寫的block,內(nèi)部使用4空格縮進(jìn)
[operation setCompletionBlock:^{
    [self.delegate newDataAvailable];
}];

//使用C語言API調(diào)用的block遵循同樣的書寫規(guī)則
dispatch_async(_fileIOQueue, ^{
    NSString* path = [self sessionFilePath];
    if (path) {
      // ...
    }
});

//較長的block關(guān)鍵字可以縮進(jìn)后在新行書寫,注意block的右括號(hào)'}'和調(diào)用block那行代碼的第一個(gè)非空字符對(duì)齊
[[SessionService sharedService]
    loadWindowWithCompletionBlock:^(SessionWindow *window) {
        if (window) {
          [self windowDidLoad:window];
        } else {
          [self errorLoadingWindow];
        }
    }];

//較長的block參數(shù)列表同樣可以縮進(jìn)后在新行書寫
[[SessionService sharedService]
    loadWindowWithCompletionBlock:
        ^(SessionWindow *window) {
            if (window) {
              [self windowDidLoad:window];
            } else {
              [self errorLoadingWindow];
            }
        }];

//龐大的block應(yīng)該單獨(dú)定義成變量使用
void (^largeBlock)(void) = ^{
    // ...
};
[_operationQueue addOperationWithBlock:largeBlock];

//在一個(gè)調(diào)用中使用多個(gè)block,注意到他們不是像函數(shù)那樣通過':'對(duì)齊的,而是同時(shí)進(jìn)行了4個(gè)空格的縮進(jìn)
[myObject doSomethingWith:arg1
    firstBlock:^(Foo *a) {
        // ...
    }
    secondBlock:^(Bar *b) {
        // ...
    }];

12.【推薦】不要用點(diǎn)分語法來調(diào)用方法,只用來訪問屬性。這樣是為了防止代碼可讀性問題。

//正確,使用點(diǎn)分語法訪問屬性
NSString *oldName = myObject.name;
myObject.name = @"Alice";

//錯(cuò)誤,不要用點(diǎn)分語法調(diào)用方法
NSArray *array = [NSArray arrayWithObject:@"hello"];
NSUInteger numberOfItems = array.count;

13.BOOL 的使用

BOOL在Objective-C中被定義為signed char類型,這意味著一個(gè)BOOL類型的變量不僅僅可以表示YES(1)和NO(0)兩個(gè)值,所以永遠(yuǎn)不要將BOOL類型變量直接和YES比較:

//錯(cuò)誤,無法確定|great|的值是否是YES(1),不要將BOOL值直接與YES比較
BOOL great = [foo isGreat];
if (great == YES)
  // ...be great!

//正確
BOOL great = [foo isGreat];
if (great)
  // ...be great!

同樣的,也不要將其它類型的值作為BOOL來返回,這種情況下,BOOL變量只會(huì)取值的最后一個(gè)字節(jié)來賦值,這樣很可能會(huì)取到0(NO)。但是,一些邏輯操作符比如&&,||,!的返回是可以直接賦給BOOL的:

//錯(cuò)誤,不要將其它類型轉(zhuǎn)化為BOOL返回
- (BOOL)isBold {
  return [self fontTraits] & NSFontBoldTrait;
}
- (BOOL)isValid {
  return [self stringValue];
}

//正確
- (BOOL)isBold {
  return ([self fontTraits] & NSFontBoldTrait) ? YES : NO;
}

//正確,邏輯操作符可以直接轉(zhuǎn)化為BOOL
- (BOOL)isValid {
  return [self stringValue] != nil;
}
- (BOOL)isEnabled {
  return [self isValid] && [self isBold];
}

14.不要使用new方法

盡管很多時(shí)候能用new代替alloc init方法,但這可能會(huì)導(dǎo)致調(diào)試內(nèi)存時(shí)出現(xiàn)不可預(yù)料的問題。Cocoa的規(guī)范就是使用alloc init方法,使用new會(huì)讓一些讀者困惑。

15.Public API要盡量簡潔

共有接口要設(shè)計(jì)的簡潔,滿足核心的功能需求就可以了。不要設(shè)計(jì)很少會(huì)被用到,但是參數(shù)極其復(fù)雜的API。如果要定義復(fù)雜的方法,使用類別或者類擴(kuò)展。

集合處理

1.【強(qiáng)制】對(duì)于可變集合類型作為屬性時(shí)使用strong,不可變集合類型使用copy

2.【強(qiáng)制】盡量不要暴露mutable類型的對(duì)象在public interface, 建議在.h定義一個(gè)Inmutable類型的屬性, 然后在.m的get函數(shù)里面返回一個(gè)內(nèi)部定義的mutable變量。保證類的不可變性。

3.使用NSNumber的語法糖

使用帶有@符號(hào)的語法糖來生成NSNumber對(duì)象能使代碼更簡潔:

NSNumber *fortyTwo = @42;
NSNumber *piOverTwo = @(M_PI / 2);
enum {
  kMyEnum = 2;
};
NSNumber *myEnum = @(kMyEnum);

4.保證NSString在賦值時(shí)被復(fù)制

NSString非常常用,在它被傳遞或者賦值時(shí)應(yīng)當(dāng)保證是以復(fù)制(copy)的方式進(jìn)行的,這樣可以防止在不知情的情況下String的值被其它對(duì)象修改。

- (void)setFoo:(NSString *)aFoo {
  _foo = [aFoo copy];
}

5.按照定義的順序釋放資源

在類或者Controller的生命周期結(jié)束時(shí),往往需要做一些掃尾工作,比如釋放資源,停止線程等,這些掃尾工作的釋放順序應(yīng)當(dāng)與它們的初始化或者定義的順序保持一致。這樣做是為了方便調(diào)試時(shí)尋找錯(cuò)誤,也能防止遺漏。

并發(fā)處理

1.【強(qiáng)制】獲取單例對(duì)象需要保證線程安全,其中的方法也要保證線程安全。

2.定義一個(gè)屬性時(shí),編譯器會(huì)自動(dòng)生成線程安全的存取方法(Atomic),但這樣會(huì)大大降低性能,特別是對(duì)于那些需要頻繁存取的屬性來說,是極大的浪費(fèi)。所以如果定義的屬性不需要線程保護(hù),記得手動(dòng)添加屬性關(guān)鍵字nonatomic來取消編譯器的優(yōu)化。

控制語句

1.【強(qiáng)制】在一個(gè) switch 塊內(nèi),每個(gè) case 要么通過 break/return 等來終止,要么注釋說明程 序?qū)⒗^續(xù)執(zhí)行到哪一個(gè) case 為止;在一個(gè) switch 塊內(nèi),都必須包含一個(gè) default 語句并且 放在最后,即使它什么代碼也沒有。

2.【強(qiáng)制】在 if/else/for/while/do 語句中必須使用大括號(hào),即使只有一行代碼,避免使用 下面的形式:if (condition) statements;

3.【推薦】推薦盡量少用 else, if-else 的方式可以改寫成:

if (condition) { 
    ...
    return obj; 
}
// 接著寫 else 的業(yè)務(wù)邏輯代碼;

4.【強(qiáng)制】請(qǐng)勿超過 3 層,超過請(qǐng)使用狀態(tài)設(shè)計(jì)模式。

正例:邏輯上超過 3 層的 if-else 代碼可以使用衛(wèi)語句,或者狀態(tài)模式來實(shí)現(xiàn)。

5.【強(qiáng)制】三目運(yùn)算符的使用

正例:

result = object ? : [self createObject];

反例:

result = object ? object : [self createObject];

6.【強(qiáng)制】對(duì)于復(fù)雜的條件判斷,要提取一個(gè)變量出來

正例:

([self canDeleteJob:job]) { ... }     
    
- (BOOL)canDeleteJob:(Job *)job {
    BOOL invalidJobState = job.JobState == JobState.New
                          || job.JobState == JobState.Submitted
                          || job.JobState == JobState.Expired;
    BOOL invalidJob = job.JobTitle && job.JobTitle.length;
     
    return invalidJobState || invalidJob;
}

反例:

if (job.JobState == JobState.New
    || job.JobState == JobState.Submitted
    || job.JobState == JobState.Expired
    || (job.JobTitle && job.JobTitle.length))
{
    //....
}

7.【強(qiáng)制】對(duì)于嵌套判斷,一旦發(fā)現(xiàn)某個(gè)條件不符合,立即返回,條理更清晰

正例:

if (!user.UserName) return NO;
if (!user.Password) return NO;
if (!user.Email) return NO;
 
return YES;

反例:

Not preferred:
BOOL isValid = NO;
if (user.UserName)
{
 
    if (user.Password)
    {
     
        if (user.Email) isValid = YES;
    }
     
}
return isValid;

注釋規(guī)范

1.【強(qiáng)制】類、類屬性、類方法的注釋必須使用文檔注釋,不得使用 //xxx 方式。

2.【強(qiáng)制】所有的類都必須添加創(chuàng)建者信息。

3.【強(qiáng)制】方法內(nèi)部單行注釋,在被注釋語句上方另起一行,使用//注釋。方法內(nèi)部多行注釋
使用/* */注釋,注意與代碼對(duì)齊。

4.【強(qiáng)制】所有的枚舉類型字段必須要有注釋,說明每個(gè)數(shù)據(jù)項(xiàng)的用途。

5.【推薦】代碼修改的同時(shí),注釋也要進(jìn)行相應(yīng)的修改,尤其是參數(shù)、返回值、異常、核心邏輯 等的修改。

6.【參考】注釋掉的代碼盡量要配合說明,而不是簡單的注釋掉。

說明:代碼被注釋掉有兩種可能性:1)后續(xù)會(huì)恢復(fù)此段代碼邏輯。2)永久不用。前者如果沒 有備注信息,難以知曉注釋動(dòng)機(jī)。后者建議直接刪掉(代碼倉庫保存了歷史代碼)。

7.【參考】好的命名、代碼結(jié)構(gòu)是自解釋的,注釋力求精簡準(zhǔn)確、表達(dá)到位。避免出現(xiàn)注釋的一個(gè)極端:過多過濫的注釋,代碼的邏輯一旦修改,修改注釋是相當(dāng)大的負(fù)擔(dān)。

8.【參考】特殊注釋標(biāo)記,請(qǐng)注明標(biāo)記人與標(biāo)記時(shí)間。注意及時(shí)處理這些標(biāo)記,通過標(biāo)記掃描,經(jīng)常清理此類標(biāo)記。線上故障有時(shí)候就是來源于這些標(biāo)記處的代碼。

  1. 待辦事宜(TODO):( 標(biāo)記人,標(biāo)記時(shí)間,[預(yù)計(jì)處理時(shí)間]) 表示需要實(shí)現(xiàn),但目前還未實(shí)現(xiàn)的功能。

  2. 錯(cuò)誤,不能工作(FIXME):(標(biāo)記人,標(biāo)記時(shí)間,[預(yù)計(jì)處理時(shí)間])
    在注釋中用 FIXME 標(biāo)記某代碼是錯(cuò)誤的,而且不能工作,需要及時(shí)糾正的情況。

其他

1.【強(qiáng)制】避免 block 的循環(huán)引用

__weak typeof(self) weakSelf = self;
myObj.myBlock =  ^{
    __strong typeof(self) strongSelf = weakSelf;
    if (strongSelf) {
      [strongSelf doSomething]; // strongSelf != nil
      // preemption, strongSelf still not nil
      [strongSelf doSomethingElse]; // strongSelf != nil
    }
    else {
        // Probably nothing...
        return;
         
    }
};

2.Delegate要使用弱引用

一個(gè)類的Delegate對(duì)象通常還引用著類本身,這樣很容易造成引用循環(huán)的問題,所以類的Delegate屬性要設(shè)置為弱引用。

/** delegate */
@property (nonatomic, weak) id <IPCConnectHandlerDelegate> delegate;

3.nil檢查
因?yàn)樵贠bjective-C中向nil對(duì)象發(fā)送命令是不會(huì)拋出異?;蛘邔?dǎo)致崩潰的,只是完全的“什么都不干”,所以,只在程序中使用nil來做邏輯上的檢查。

另外,不要使用諸如nil == Object或者Object == nil的形式來判斷。

//正確,直接判斷
if (!objc) {
    ... 
}

//錯(cuò)誤,不要使用nil == Object的形式
if (nil == objc) {
    ... 
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 引言 一直以來都是在談如何開發(fā), 如開發(fā)的小技巧小經(jīng)驗(yàn) 今天為什么突然說起編程規(guī)范來了呢? 因?yàn)樵谖铱磥? 編程規(guī)...
    諾之林閱讀 604評(píng)論 1 5
  • 方法聲明和定義 -或者+和返回類型之間須使用一個(gè)空格,括號(hào)要同行并有一個(gè)空格 方法應(yīng)該像這樣: 如果函數(shù)名字太長,...
    Dayon閱讀 281評(píng)論 0 1
  • 本文記錄一下Objective-C編程規(guī)范以及一些建議,可能后續(xù)會(huì)有些修改和補(bǔ)充,至于初衷是最近接手的項(xiàng)目中代碼"...
    SuperMario_Nil閱讀 1,922評(píng)論 2 13
  • 傳送門 解讀阿里Java開發(fā)手冊(cè)(v1.1.1) - 異常日志 前言 阿里Java開發(fā)手冊(cè)談不上圣經(jīng),但確實(shí)是大量...
    kelgon閱讀 4,466評(píng)論 4 50
  • 佛啊佛佛啊佛,世人拜禮誠求佛,佛途迢迢徑難尤,佛在心中不坐佛,佛在哪里成了佛,又是誰來引佛成。佛啊佛佛啊佛,南無阿...
    靛羽風(fēng)漣閱讀 1,505評(píng)論 0 1

友情鏈接更多精彩內(nèi)容