http://blog.csdn.net/zhaoxy_thu/article/details/9090963命名規(guī)范類命名l 首字母大寫,之后每個單詞首字母都大寫 l 使用能夠反映類功能的名詞短語 l 文件和類同名 l 舉例:BaseClient、ImageStore 特殊類命名l 如果是視圖控制器的子類應(yīng)添加后綴“ViewController”或者“Controller” l 如果是視圖的子類應(yīng)添加后綴“View” l 如果是按鈕的子類應(yīng)添加后綴“Button” …… l 舉例:SettingsViewController、NavigationView 分類(類別)命名l 與類命名相同,此外需添加要擴(kuò)展的類名和“+” l 舉例:NSString+URLEncoding 協(xié)議(委托)命名l 與類命名相同,此外需添加“Delegate”后綴 l 舉例:ReplyViewDelegate 方法命名l 首字母小寫,之后每個單詞首字母都大寫 l 方法名使用動詞短語 l 舉例:- (void)setPostValue:(int)value 方法參數(shù)命名l 首字母小寫,之后每個單詞首字母都大寫 l 具有足夠的說明性 l 不需要添加類型前綴 l 舉例:- (void)sendUserInfo:(NSDictionary *)userInfo 變量命名l 首字母小寫,之后每個單詞首字母都大寫 l 具有足夠的說明性 l 成員變量不需要添加“_m”前綴 l 成員變量添加“_”前綴 常量l 常量(預(yù)定義,局部常量等)使用小寫k開頭的駝峰法 l 舉例:kInvalidHandle , kWritePerm l 枚舉類型命名首字母大寫,之后每個單詞首字母都大寫,最后加“s” l 枚舉變量使用枚舉類型去掉“s”作為前綴,每個單詞首字母大寫,中間不允許加下劃線 l 舉例: typedef enum UIControlEvents{ UIControlEventTouchDown, UIControlEventTouchUpInside }UIControlEvents; 圖片命名l 使用英文,首字母大寫,之后每個單詞首字母都大寫 l 添加模塊名作為前綴,避免沖突 l 圖片應(yīng)該與類文件一樣,按模塊分組放置 分組命名l 使用英文,首字母大寫,之后每個單詞首字母都大寫 l 每個分組使用模塊的名字 l 使用的開源庫統(tǒng)一放在“Library”分組下 l 使用的公共組件統(tǒng)一放在“Common”分組下 l 視圖控制器及AppDelegate統(tǒng)一放在“Controllers”分組下 書寫規(guī)范注釋l 文件都包含文件頭,要說明文件名、作者、創(chuàng)建時間、變更記錄 l 多人協(xié)作完成項目時,public接口的每個方法都應(yīng)該添加關(guān)于函數(shù),參數(shù),返回值以及副作用的注釋 l 當(dāng)if語句的判斷條件復(fù)雜時,需要用注釋說明判斷內(nèi)容 l 接口類(繼承于BaseClient)的頭文件每個方法前都應(yīng)該注明方法的作用 方法l 留一個空格在-或+和返回類型之間,但參數(shù)列表里的參數(shù)之間不要留間隔,每個冒號之前都必須有對該參數(shù)的說明詞,如: p - (void)doSomethingWithString:(NSString *)string number:(int)num l 如果參數(shù)過多,推薦每個參數(shù)各占一行。使用多行的情況下,在參數(shù)前加冒號用于對齊,如: p -(void)doSomethingWith:(GTMFoo *)theFoo rect:(NSRect)theRect interval:(float)theInterval 其他規(guī)范l 操作符前后都要加空格 l 避免相同的代碼段在多個地方出現(xiàn) l 語句嵌套層次不得超過3層 l 每個實現(xiàn)文件建議在500行以內(nèi),不能超過1000行,超過之后應(yīng)考慮通過抽象類對代碼進(jìn)行重構(gòu) l 及時刪除或注釋掉無用的代碼 l UITableViewCell里面的network client都要委托出來 l 點擊按鈕之后需要切換按鈕圖片,當(dāng)這兩張圖片沒有關(guān)聯(lián)時(例如一張圖片相比另一張圖片有選中效果),不應(yīng)該設(shè)置為UIControlSelected l 控件布局使用相對坐標(biāo) l 確定不使用的代碼應(yīng)該刪除=========================== 正文: · 格式化代碼 ? 指針“*”號的位置 ? 如:NSString *varName; ? 空格 VS tabs ? 只允許使用空格,將編輯器設(shè)置為1個TAB = 2個字符縮進(jìn) ? 每行的長度 ? 每行最多不得超過100個字符 ? 以15寸Macbook Pro的大小,每行100個字符時能最大化地同時容下編輯器和iPhone模擬器 ? Google的80字符的標(biāo)準(zhǔn)有點少,這導(dǎo)致過于頻繁的換行(Objectve-C的代碼一般都很長) ? 通過 “Xcode => Preferences => TextEditing => 勾選Show Page Guide / 輸入 100 => OK” 來設(shè)置提醒 ? 方法的聲明和定義 ? 在 - OR + 和返回值之間留1個空格,方法名和第一個參數(shù)間不留空格。如: - (void)doSomethingWithString:(NSString *)theString { ... } ? 當(dāng)參數(shù)過長時,每個參數(shù)占用一行,以冒號對齊。如: - (void)doSomethingWith:(GTMFoo *)theFoo rect:(NSRect)theRect interval:(float)theInterval { ... } ? 如果方法名比參數(shù)名短,每個參數(shù)占用一行,至少縮進(jìn)4個字符,且為垂直對齊(而非使用冒號 對齊)。如: - (void)short:(GTMFoo *)theFoo longKeyword:(NSRect)theRect evenLongerKeyword:(float)theInterval { ... } ? 方法的調(diào)用 ? 調(diào)用方法沿用聲明方法的習(xí)慣。例外:如果給定源文件已經(jīng)遵從某種習(xí)慣,繼續(xù)遵從那種習(xí)慣。 ? 所有參數(shù)應(yīng)在同一行中,或者每個參數(shù)占用一行且使用冒號對齊。如: [myObject doFooWith:arg1 name:arg2 error:arg3]; 或 [myObject doFooWith:arg1 name:arg2 error:arg3]; ? 和方法的聲明一樣,如果無法使用冒號對齊時,每個參數(shù)一行、縮進(jìn)4個字符、垂直對其(而非 使用冒號對齊)。如: [myObj short:arg1 longKeyword:arg2 evenLongerKeyword:arg3]; ? @public 和 @private ? @public 和 @private使用單獨一行,且縮進(jìn)1個字符 ? Protocals ? 類型標(biāo)示符、代理名稱、尖括號間不留空格。 ? 該規(guī)則同樣適用于:類聲明、實例變量和方法聲明。如: @interface MyProtocoledClass : NSObject<NSWindowDelegate> { @private id<MyFancyDelegate> _delegate; } - (void)setDelegate:(id<MyFancyDelegate>)aDelegate; @end ? 如果類聲明中包含多個protocal,每個protocal占用一行,縮進(jìn)2個字符。如: @interface CustomViewController : ViewController< AbcDelegate, DefDelegate > { ... } · 命名 ? 類名 ? 類名(及其category name 和 protocal name)的首字母大寫,寫使用首字母大寫的形式 分割單詞 ? 在面向特定應(yīng)用的代碼中,類名應(yīng)盡量避免使用前綴,每個類都使用相同的前綴影響可讀性。 ? 在面向多應(yīng)用的代碼中,推薦使用前綴。如:GTMSendMessage ? Category Name ? 待完善 ? 方法名 ? 方法名的首字母小寫,且使用首字母大寫的形式分割單詞。方法的參數(shù)使用相同的規(guī)則。 ? 方法名+參數(shù)應(yīng)盡量讀起來像一句話(如:)。在這里查看蘋果對方法命名的規(guī)范。 ? getter的方法名和變量名應(yīng)相同。不允許使用“get”前綴。如: - (id) getDelegate; // 禁止 - (id)delegate; // 對頭 ? 本規(guī)則僅針對Objective-C代碼,C++代碼使用C++的習(xí)慣 ? 變量名 ? 變量名應(yīng)使用容易意會的應(yīng)用全稱,且首字母小寫,且使用首字母大寫的形式分割單詞 ? 成員變量使用“_”作為前綴(如:“NSString *_varName;”。雖然這與蘋果的標(biāo)準(zhǔn)(使 用“_”作為后綴)相沖突,但基于以下原因,仍使用“_”作為前綴。 ? 使用“_”作為前綴,更容易在有代碼自動補(bǔ)全功能的IDE中區(qū)分“屬性 (self.userInfo)”和“成員變量(_userInfo)” ? 常量(#define, enums, const等)使用小寫“k”作為前綴,首字母大寫來分割單詞。如: kInvalidHandle · 注釋 ? 待完善 · Cocoa 和 Objective-C特有的規(guī)則 ? 成員變量使用 @private。如: @interface MyClass : NSObject { @private id _myInstanceVariable; } // public accessors, setter takes ownership - (id)myInstanceVariable; - (void)setMyInstanceVariable:(id)theVar; @end ? Indentify Designated Initializer ? 待完善 ? Override Desingated Initializer ? 待完善 ? 初始化 ? 在初始化方法中,不要將變量初始化為“0”或“nil”,那是多余的 ? 內(nèi)存中所有的新創(chuàng)建的對象(isa除外)都是0,所以不需要重復(fù)初始化為“0”或“nil” ? 避免顯式的調(diào)用 +new 方法 ? 禁止直接調(diào)用 NSObject 的類方法 +new,也不要在子類中重載它。使用alloc和init方法 ? 保持公共API的簡潔性 ? 待完善 ? #import VS #include ? 使用 #import 引入Ojbective-C和Ojbective-C++頭文件,使用 #include 引入C和C++頭 文件 ? import根框架(root frameworks),而非各單個文件 ? 雖然有時我們僅需要框架(如Cocoa 或 Foundation)的某幾個頭文件,但引入根文件編譯 器會運行的更快。因為根框架(root frameworks)一般會預(yù)編譯,所以加載會更快。再次強(qiáng) 調(diào):使用 #import 而非 #include 來引入Objective-C框架。如: #import <Foundation/NSArray.h> // 禁止 #import <Foundation/NSString.h> ... #import <Foundation/Foundation.h> // 對頭 ? 創(chuàng)建對象時盡量使用autorelease ? 創(chuàng)建臨時對象時,盡量同時在同一行中 autorelease 掉,而非使用單獨的 release 語句 ? 雖然這樣會稍微有點慢,但這樣可以阻止因為提前 return 或其他意外情況導(dǎo)致的內(nèi)存泄露。 通盤來看這是值得的。如: // 避免這樣使用(除非有性能的考慮) MyController* controller = [[MyController alloc] init]; // ... 這里的代碼可能會提前return ... [controller release]; // 這樣更好 MyController* controller = [[[MyController alloc] init] autorelease]; ? 先autorelease,再retain ? 在為對象賦值時,遵從“先autorelease,再retain” ? 在將一個新創(chuàng)建的對象賦給變量時,要先將舊對象release掉,否則會內(nèi)存泄露。市面上有很 多方法來handle這種情況,這里選擇“先autorelease,再retain”的方法,這種方法不易引 入error。注意:在循環(huán)中這種方法會“填滿”autorelease pool,稍稍影響效率,但是 Google和我( :P )認(rèn)為這個代價是可以接受的。如: - (void)setFoo:(GMFoo *)aFoo { [foo_ autorelease]; // 如果foo_和aFoo是同一個對象(foo_ == aFoo), dealloc不會被調(diào)用 foo_ = [aFoo retain]; } ? dealloc的順序要與變量聲明的順序相同 ? 這有利于review代碼 ? 如果dealloc中調(diào)用其他方法來release變量,將被release的變量以注釋的形式標(biāo)注清楚 ? NSString的屬性的setter使用“copy” ? 禁止使用retain,以防止意外的修改了NSString變量的值。如: - (void)setFoo:(NSString *)aFoo { [foo_ autorelease]; foo_ = [aFoo copy]; } 或 @property (nonatomic, copy) NSString *aString; ? 避免拋出異常(Throwing Exceptions) ? 待完善 ? 對 nil 的檢查 ? 僅在有業(yè)務(wù)邏輯需求時檢查 nil,而非為了防止崩潰 ? 向 nil 發(fā)送消息不會導(dǎo)致系統(tǒng)崩潰,Objective-C運行時負(fù)責(zé)處理。 ? BOOL陷阱 ? 將int值轉(zhuǎn)換為BOOL時應(yīng)特別小心。避免直接和YES比較 ? Objective-C中,BOOL被定義為unsigned char,這意味著除了 YES (1) 和 NO (0)外它 還可以是其他值。禁止將int直接轉(zhuǎn)換(cast or convert)為BOOL。 ? 常見的錯誤包括:將數(shù)組的大小、指針值或位運算符的結(jié)果轉(zhuǎn)換(cast or convert)為 BOOL,因為該BOOL值的結(jié)果取決于整型值的最后一位 ? 將整型值轉(zhuǎn)換為BOOL的方法:使用三元運算符返回YES / NO,或使用位運算符(&&, ||, !) ? BOOL、_Bool和bool之間的轉(zhuǎn)換是安全的,但是BOOL和Boolean間的轉(zhuǎn)換不是安全的,所以 將Boolean看成整型值。 ? 在Objective-C中,只允許使用BOOL ? 如: // 禁止 - (BOOL)isBold { return [self fontTraits] & NSFontBoldTrait; } - (BOOL)isValid { return [self stringValue]; } // 對頭 - (BOOL)isBold { return ([self fontTraits] & NSFontBoldTrait) ? YES : NO; } - (BOOL)isValid { return [self stringValue] != nil; } - (BOOL)isEnabled { return [self isValid] && [self isBold]; } ? 禁止直接將BOOL和YES/NO比較,如: // 禁止 BOOL great = [foo isGreat]; if (great == YES) ... // 對頭 BOOL great = [foo isGreat]; if (great) ... ? 屬性 ? 命名:與去掉“_”前綴的成員變量相同,使用@synthesize將二者聯(lián)系起來。如: // abcd.h @interface MyClass : NSObject { @private NSString *_name; } @property (copy, nonatomic) NSString *name; @end // abcd.m @implementation MyClass @synthesize name = _name; @end ? 位置:屬性的聲明緊隨成員變量塊之后,中間空一行,無縮進(jìn)。如上例所示 ? 嚴(yán)把權(quán)限:對不需要外部修改的屬性使用readonly ? NSString使用copy而非retain ? CFType使用@dynamic, 禁止使用@synthesize ? 除非必須,使用nonatomic · Cocoa Pattern ? Delegate Pattern(委托) ? delegate對象使用assign,禁止使用retain。因為retain會導(dǎo)致循環(huán)索引導(dǎo)致內(nèi)存泄露, 并且此類型的內(nèi)存泄露無法被Instrument發(fā)現(xiàn),極難調(diào)試 ? 成員變量命名為_delegate,屬性名為delegate ? Model/View/Controller ? Model和View分離 ? 不多解釋 ? Controller獨立于View和Controller ? 不要在與view相關(guān)的類中添加過多的業(yè)務(wù)邏輯代碼,這讓代碼的可重用性很差 ? Controller負(fù)責(zé)業(yè)務(wù)邏輯代碼,且Controller的代碼與view盡量無關(guān) ? 使用 @protocal 定義回調(diào)APIs,如果并非所有方法都是必須的,使用 @optional 標(biāo)示 · 其他 ? init方法和dealloc方法是是最常用的方法,所以將他們放在類實現(xiàn)的開始位置 ? 使用空格將相同的變量、屬性對齊,使用換行分組 =========================== 一、文檔結(jié)構(gòu)管理 1.建立Libraries文件夾,所有第三方庫放入其中。 2.建立Utilities文件夾,自已封裝的類放入其中。 3.建立Constants.h頭文件,所有的常量定義于其中。Constants.h文件放入Main文件組里面。 4.每個功能塊放入一個Group,在目錄里建立實際文件夾管理。 5.程序資源文件放入Supporting Files文件夾中。如.plist、數(shù)據(jù)庫資料等。 6.在Supporting Files文件夾下建立Image、Music和Video等相關(guān)文件夾。圖片、音頻、視頻等資源分別放入其中。圖片資源以程序邏輯框架建立相應(yīng)實體文件夾管理,若多個功能塊共用的,建立Common文件夾,放入其中。 二、編碼規(guī)范 說明:為了不影響閱讀,一個類的代碼行數(shù)盡量不要超過300行;一個方法盡量不要超過30行。有超過的在重構(gòu)的時候想辦法分解。 1.每個.h文件最開始處用簡短文字說明一下該類的功能邏輯。 2.引入其它類時,若要作為實例變量的在.h中引入。否則在.m中引入。 3.@interface與@implementation與#import 之間空一行。@synthesize緊接著@implementation寫。 4.a:聲明實例變量一律以屬性聲明。 b:其它類要訪問的實例變量和方法在.h文件中聲明,否則聲明于.m文件中。 c:實例變量及方法以功能塊放在一起,實現(xiàn)一個功能的連續(xù)著放在一起,另一個功能的空一行開始聲明。 d:實例變量緊接@interface后開始,方法在實例變量后空一行開始。 e:每個功能塊可作簡單說明,單個實例變量方法可不作說明,關(guān)鍵的或特殊的變量或方法單獨作說明。注釋放于變量聲明上一行。 5.類中第個功能模塊以 #pragma mark - 分隔,上空兩行,下空一行。 6.NSLog在測試完成后一律刪除。 7.對于系統(tǒng)的常用類作實例變量聲明時加入后綴: UIViewController:VC UIImage:Img UIImageView:ImgView UIView:View UILabel:Lbl UIButton:Btn UINavigationBar:NBar UIToolBar:TBar UISearchBar:SBar UITextField:TextField UITextView:TextView NSArray:Array NSMutableArray:MArray NSDictionary:Dict NSMutableDictionary:MDict NSString:Str NSMutableString:MStr NSSet:Set NSMutableSet:MSet 8.程序中變量、方法命名盡量能以字面意思表示功能,對于需要用注釋來解釋的部分代碼,注釋以如下格式表述: /** * 方法或變量說明 * @param 參數(shù)1說明(針對方法) * @param 參數(shù)2說明(針對方法) * @return 若方法有返回值則對返回值作說明 */
三、Xcode配置 1.全部統(tǒng)一用ARC。 2.用git管理代碼。 3.在項目.pch文件加入一段去除release的NSLog代碼: #ifndef __OPTIMIZE__ #define NSLog(...) NSLog(__VA_ARGS__) #else #define NSLog(...) {} #endif =========================== 代碼寫的不夠漂亮工整符合規(guī)范?大家的代碼風(fēng)格過于迥異閱讀困難? 作為一個程序猿來說我越來越感覺到養(yǎng)成一個良好的代碼風(fēng)格的重要性,總結(jié)一下OC編程中的一些代碼規(guī)范(蘋果官方推薦的)。 參考資料:IOS Developer Library 對建議的代碼規(guī)范的說明 ,我也發(fā)現(xiàn)有同學(xué)翻譯成中文版本了。 類(Class)命名原則 就拿“NSMutableArray”來說 NS --- 前綴(Prefix)我的理解是表示類所屬的“包”,這里的NS就表示的是Cocoa的基礎(chǔ)類庫,取公司名項目名什么的。(NS是NextStep公司的簡寫,里面的淵源就不細(xì)說了- -)前綴的意義就在于比較直觀的劃分了類的所屬和范圍。像Cocos2d里的前綴就是CC,box2d里面是B2,UserInterface->UI,CoreFoundation->CF,CoreGraphics->CG。如果我也能寫一個開源架構(gòu)或模塊的話,我應(yīng)該會取“SY”或是“Sunny”吧 :)
成員變量與屬性存取器(Accessor)命名原則 這也是讓我糾結(jié)了挺久,一直不懂為什么很多代碼里面類成員變量出現(xiàn)了下劃線"_",而屬性存取方法@property聲明時不加下劃線,實現(xiàn)時@synthesize又令兩個名字相等。 @interface SunnyTest : NSObject { NSArray * _array; } @property (nonatomic,retain) NSArray * array; @end
@implementation SunnyTest @synthesize array = _array; @end 這樣做的原因很簡單,就是不暴露實例的成員變量,外界只能用@property聲明的存取名來訪問成員變量,所以就用下滑線加以區(qū)分。 但在類內(nèi)方法訪問成員變量時就直接使用帶下劃線的名字,個人認(rèn)為不要用self.xxxxx來使用,因為使用存取器本來就是對外的,在內(nèi)部使用可能會造成一些不必要的錯誤,比如: self.array = [[NSArray alloc] init]; //內(nèi)存泄露 這時就會造成內(nèi)存泄露,因為[[NSArray alloc] init]生成NSArray對象之后賦值給self.array,由于array的存取方法中包含retain,這會使retainCount變成2,而實際應(yīng)該是1,內(nèi)存泄露且很難發(fā)現(xiàn)。 改成這樣的寫法也是蘋果官方推薦的。 _array = [[NSArray alloc] init];
方法(Method)起名規(guī)則 一個規(guī)范的方法讀起來應(yīng)該像一句完整的話,讀過之后便知函數(shù)的作用。執(zhí)行性的方法應(yīng)該以動詞開頭,小寫字母開頭,返回性的方法應(yīng)該以返回的內(nèi)容開頭,但之前不要加get。
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject; + (id)arrayWithArray:(NSArray *)array; 如果有參數(shù),函數(shù)名應(yīng)該作為第一個參數(shù)的提示信息,若有多個參數(shù),在參數(shù)前也應(yīng)該有提示信息(一般不必加and) 一些經(jīng)典的操作應(yīng)該使用約定的動詞,如initWith,insert,remove,replace,add等等。 =========================== Objective-C編碼規(guī)范:26個方面解決iOS開發(fā)問題黃金路徑當(dāng)使用條件語句編碼時,左手邊的代碼應(yīng)該是"golden" 或 "happy"路徑。也就是不要嵌套if語句,多個返回語句也是OK。 應(yīng)該:
不應(yīng)該:
錯誤處理當(dāng)方法通過引用來返回一個錯誤參數(shù),判斷返回值而不是錯誤變量。 應(yīng)該:
不應(yīng)該:
在成功的情況下,有些Apple的APIs記錄垃圾值(garbage values)到錯誤參數(shù)(如果non-NULL),那么判斷錯誤值會導(dǎo)致false負(fù)值和crash。 單例模式單例對象應(yīng)該使用線程安全模式來創(chuàng)建共享實例。
這會防止possible and sometimes prolific crashes。 換行符換行符是一個很重要的主題,因為它的風(fēng)格指南主要為了打印和網(wǎng)上的可讀性。 例如:
一行很長的代碼應(yīng)該分成兩行代碼,下一行用兩個空格隔開。
Xcode工程物理文件應(yīng)該與Xcode工程文件保持同步來避免文件擴(kuò)張。任何Xcode分組的創(chuàng)建應(yīng)該在文件系統(tǒng)的文件體現(xiàn)。代碼不僅是根據(jù)類型來分組,而且還可以根據(jù)功能來分組,這樣代碼更加清晰。 盡可能在target的Build Settings打開"Treat Warnings as Errors,和啟用以下additional warnings。如果你需要忽略特殊的警告,使用Clang's pragma feature。 其他Objective-C編碼規(guī)范如果我們的編碼規(guī)范不符合你的口味,可以查看其他的編碼規(guī)范: 譯者簡介:劉耀柱(@Sam_Lau_Dev),iOS Developer兼業(yè)余Designer,參與開發(fā)技術(shù)前線iOS項目翻譯,個人博客:http://www.jianshu.com/users/256fb15baf75/latest_articles,GitHub:https://github.com/samlaudev。 =========================== |
|