談談iOS中的命名規范

轉載:http://liumh.com/
本文談談 iOS 開發中的命名規范,主要涉及常量命名、枚舉命名、類及其方法命名,以及分類及其方法命名。如果你找的是官網的編碼規范,請移步: Coding Guidelines for Cocoa。當然本文會講一些官網沒有的東西。

<a id="ConstantNamed"></a>常量命名

iOS 開發中,肯定避免不了要命名一些常量,那么,我們應該怎樣來命名常量呢?在討論上述問題前,先來了解定義常量的兩種方式。

  • 第一種,使用 #define預處理定義常量。例如:
    #define ANIMATION_DURATION 0.3

定義一個 ANIMATION_DURATION常量來表示 UI 動畫的一個常量時間,這樣,代碼中所有使用ANIMATION_DURATION的地方都會被替換成 0.3,但是這樣定義的常量無類型信息,且如果
你在調試時想要查看 ANIMATION_DURATION的值卻無從下手,因為在預處理階段ANIMATION_DURATION就已經被替換了,不便于調試。因此,棄用這種方式定義常量。

  • 第二種,使用類型常量。將上面的預處理定義常量修改成類型常量:
    static const NSTimeInterval kAnimationDuration = 0.3;

這樣就為常量帶入了類型信息,那么定義類型常量又有什么規范呢?
對于局限于某編譯單元(實現文件)的常量,通常以字符k
開頭,例如上文中的 kAnimationDuration
,且需要以 static const 修飾,例如:
static const NSTimeInterval kAnimationDuration = 0.3;

對于定義于類頭文件的常量,外部可見,則通常以定義該常量所在類的類名開頭,例如 EOCViewClassAnimationDuration, 仿照蘋果風格,在頭文件中進行 extern 聲明,在實現文件中定義其值:

EOCViewClass.h
extern const NSTimeInterval EOCViewClassAnimationDuration;
EOCViewClass.m
const NSTimeInterval EOCViewClassAnimationDuration = 0.3;

對于字符串常量,則會像這樣:

EOCViewClass.h
EOCViewClass.hextern NSString *const EOCViewClassStringConstant;

EOCViewClass.m
NSString *const EOCViewClassStringConstant = @"EOCStringConstant";

常量定義是從右往左解讀,上面的示例中就是定義了一個常量指針,其指向一個 NSString 對象, 這樣該常量就不會被隨意修改。至于這種暴露出來的類常量最前面是否加上字母k, 可以根據自己習慣在團隊中進行約定,因為從 iOS 的接口中我看到這兩種情況都有, 如

NSString *const UIApplicationLaunchOptionsRemoteNotificationKey;
NSString *const UIApplicationLaunchOptionsLocalNotificationKey;

NSString *const kCAAnimationCubic;
NSString *const kCAAnimationCubicPaced;

<a id="Status_opation_statusCode"></a>用枚舉表示狀態、選項、狀態碼

項目中,可用枚舉來表示一系列的狀態、選項和狀態碼。例如 iOS SDK 中表示 UICollectionView 滑動方向的枚舉定義如下:

typedef NS_ENUM(NSInteger, UICollectionViewScrollDirection) { 
     UICollectionViewScrollDirectionVertical,
     UICollectionViewScrollDirectionHorizontal
};

或者定義 UITableView Style 的枚舉:

typedef NS_ENUM(NSInteger, UITableViewStyle) { 
    UITableViewStylePlain, // regular table view 
    UITableViewStyleGrouped // preferences style table view
};

從這里可以看出,定義的枚舉類型名稱應以 2~3 個大寫字母開頭,而這通常與項目設置的類文件前綴相同,跟隨其后的命名應采用駝峰命名法則,命名應準確表述枚舉表示的意義,枚舉中各個值都應以定義的枚舉類型開頭,其后跟隨各個枚舉值對應的狀態、選項或者狀態碼。對于需要以按位或操作來組合的枚舉都應使用 NS_OPTIONS 宏來定義,例如 SDK 中:

typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing)   
    UIViewAutoresizingNone = 0, 
    UIViewAutoresizingFlexibleLeftMargin = 1 << 0, 
    UIViewAutoresizingFlexibleWidth = 1 << 1, 
    UIViewAutoresizingFlexibleRightMargin = 1 << 2, 
    UIViewAutoresizingFlexibleTopMargin = 1 << 3, 
    UIViewAutoresizingFlexibleHeight = 1 << 4, 
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};

這樣定義的選項能夠以 按位或操作符 來進行組合,枚舉中每個值均可啟用或者禁用某一選項,在使用時,可以使用 按位與操作符 來檢測是否啟用了某一選項,如下:

UIViewAutoresizing resizing = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    if (resizing & UIViewAutoresizingFlexibleWidth) {// 
          UIViewAutoresizingFlexibleWidth is set
    };

另外,我們可能使用 switch 語句時,會在最后加上 default 分支,但是若用枚舉定義狀態機,則最好不要使用 default 分支,因為如果稍后再加了一種狀態,那么編譯器就會發出警告,提示新加入的狀態并未在 switch 分支中處理。假如寫上了 default 分支,那么它就會處理這個新狀態,從而導致編譯器不發出警告,用 NS_ENUM 定義其他枚舉類型時也要注意此問題。例如在定義代表 UI 元素樣式的枚舉時,通常要確保 switch 語句能正確處理所有樣式。

小結一下:
  • 應該用枚舉來表示狀態機的狀態、傳遞給方法的選項以及狀態碼等值,給這些值起個易懂的名字。
  • 如果把傳遞給某個方法的選項表示為枚舉類型,而多個選項又可同時使用,那么就將各選項值定義為 2 的冪,以便通過按位或操作將其組合起來。
  • 用 NS_ENUM 與 NS_OPTIONS 宏來定義枚舉類型,并指明其底層數據類型。這樣就可以確保枚舉是用開發者所選的底層數據類型實現出來的,而不是采用編譯器所選的類型。
  • 在處理枚舉類型的 switch 語句中不要實現 default 分支。這樣加入新的枚舉值之后,編譯器就會發出警告提示,switch 還有未處理的枚舉值。

<a id="Class_method"></a>類及其方法命名

Objective-C 沒有其他語言那種內置的命名空間(namespace)機制。因此,我們在起名時要設法避免潛在的命名沖突,否則很容易就重名了。避免此問題的唯一方法就是變相實現命名空間: 為所有名稱都加上適當前綴。所選前綴可以是與公司、應用程序或者二者皆有關聯的名字。使用 Cocoa 和 Cocoa Touch 創建應用程序時一定要注意,Apple 宣傳其保留使用所有“兩個字母前綴”(tow-letter prefixed)的權利。所以你自己選用的前綴應該是三個字母的。你可以在蘋果官網 Class Names Must Be Unique Across an Entire App 看到上述說明:

In order to keep class names unique, the convention is to use prefixes on all classes. You’ll have noticed that Cocoa and Cocoa Touch class names typically start either with NS or UI. Two-letter prefixes like these are reserved by Apple for use in framework classes.
Your own classes should use three letter prefixes. These might relate to a combination of your company name and your app name, or even a specific component within your app.
You should also name your classes using a noun that makes it clear what the class represents, like these examples from Cocoa and Cocoa Touch:

NSWindow | CAAnimation | NSWindowController | NSManagedObjectContext

另外,在文檔 Coding Guidelines for Cocoa 中提到:

Use prefixes when naming classes, protocols, functions, constants, and typedef structures. Do not use prefixes when naming methods; methods exist in a name space created by the class that defines them. Also, don’t use prefixes for naming the fields of a structure.

這里需要說明兩點:

  • 上述所說的functions指的是純 C 函數。對于純 C 函數和全局變量,不論其處于頭文件或者其實現文件中,在編譯好的目標文件中,這些名稱要算作“頂級符號”(top-level symbol)的。因此我們總應該為這種 C 函數的名字加上前綴。通常情況下,這類 C 函數我們可以以定義其類的名字作為前綴。這樣,在調試時,若此符號出現在棧回溯信息中,則很容易就能判明問題源自哪塊代碼。例如:
ACLSoundPlayer.h
#import <Foundation/Foundation.h>
@interface ACLSoundPlayer :NSObject
@endACLSoundPlayer.m
#import "ACLSoundPlayer.h"
#import <AudioToolbox/AudioToolbox.h>
  void ACLSoundPlayerCompletion(SystemSoundID ssID, void *clientData) {
  }
@implementation ACLSoundPlayer
@end
  • 上述引用說到不應該為 Objective-C methods 添加前綴,我覺得應該添加一個例外,當我們定義分類中的方法時,則總應該為其添加前綴,這會在下一條詳細說明。

最后一種情況,若為第三庫編寫自己的代碼,并準備將其發布為程序庫供他人開發應用程序所用時,你應該給你所用的那份第三方庫代碼都加上你自己的前綴。為便于說明,假如你要發布的程序庫叫 EOCLibrary,你所使用的第三方庫叫 XYZLibrary,則你應該把你使用的 XYZLibrary 中所有名字都冠以 EOC
, 成為 EOCXYZLibrary, 原因如下:

  • 你的程序所包含的那個第三方庫也許還會為應用程序本身所引入。
  • 你可能會想,讓應用程序本身不要直接引入 XYZLibrary,改用 EOCLibrary 中使用的那個,但是,應用程序也許還會引入另一個名為 ABCLibrary 的第三方庫,而該庫中又包含了 XYZLibrary。此時,如果你和 ABCLibrary 的作者都不給各自所用的 XYZLibrary 加前綴,那么應用程序依然會出現重復符號錯誤。
  • 你的庫里所引用的第三方庫是 X 版本的,而應用程序卻需要引用第三庫的 Y 版本的功能。

對于類中的方法命名,應遵循以下規則:

  • 如果方法的返回值是新建的,那么方法名的首個詞應是返回值的類型,例如: +stringWithString:。除非前面還有修飾語,例如 localizedString。屬性的存取方法不遵循這種命名方式。
  • BOOL屬性應加 is 前綴。如果某方法返回非屬性的 Boolean 值,那么應該根據你功能,選用 has 或 is 當前綴。

<a id="Category_method"></a>分類及其方法命名

分類機制通常用于向無源碼的既有類中新增功能。分類中的方法是直接加在類里面的,它們就好比這個類固有的方法,將分類方法加入類中這一操作是在運行期系統加載分類時完成的。運行期系統會把分類中所實現的每個方法都加入類的方法列表中。如果類中本來就有此方法,而分類中又實現了一次,那么分類中的方法會覆蓋原來那一份實現代碼。實際上可能會發生很多次覆蓋,比如某個分類中的方法覆蓋了“主實現”中的相關方法,而另外一個分類中的方法又覆蓋了這個分類中的方法,多次覆蓋的結果以最后一個分類為準。當有多份實現時,無法確定運行時使用的是那份實現。由這樣引發的 bug 很難追查。

那么,如何來最大限度的避免這種覆蓋呢?

在 iOS 開發中,沒有命名空間的概念。通常,我們通過為項目中所有類命名加上特有的前綴來實現命名空間的功能,來避免可能發生的與使用第三方庫中的方法命名相同。同樣的,這里我們也是為分類,以及分類中的所有方法都加上特定前綴。這個前綴應該與應用程序庫中其他地方所用的前綴相同,通常會使用公司名或應用程序名來做決定。例如來編寫一個判斷對象是否為空的分類方法:

NSObject+ACLNetworkingMethods.h
@interface NSObject (ACLNetworkingMethods)
- (BOOL)acl_isEmptyObject;
@end

這里為分類名以及分類中的方法加上了 ACL
的前綴。注意在方法中,需前綴小寫。

另外,使用分類時,不要刻意覆寫分類中的方法,尤其是當你把代碼發布為程序庫供其他開發者使用時,因為你無法決定其他開發者需要的是方法哪份實現。

總結:

  • 向第三方類中添加分類時,總應該給分類名稱加上你專有的前綴,前綴須大寫。
  • 向第三方類中添加分類時,總應該給分類中的方法名加上你專有的前綴,前綴須小寫,且以下劃線連接前綴與方法名。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內容