在開發過程中,我們不僅要去看別人的程式碼,也要讓別人看我們的程式碼。那麼,有一個良好的編碼習慣將會非常重要。下面將會羅列使用Objective-C來開發iOS的編碼建議。
【1】任意函式長度不得超過50行。(其實很容易就超過50行,這就要考慮程式碼抽取了。)
【2】任意行程式碼不能超過80字元。(其實也很容易超過80字元,可以考慮多行顯示,比如有多個引數時,可以每個引數放一行。)可以在Xcode中設定超過80個字元的提醒,選中“Page guide at column”.設定完之後就會在程式碼80個字元處有一條豎線。[Xcode選單–>Preferences–>Text Editing–>勾選Page guide at column.]
【3】在每個方法的定義前留白一行,也就是在方法和方法之間留空一行。
【4】功能相近的方法要放在一起,並推薦使用#pragma mark – *來導航程式碼,切分程式碼塊。這樣可以方便函式的查詢。並且可以使用快捷鍵control+6 來快速查詢方法的位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#pragma mark - 生命週期 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. } #pragma mark - 代理 MapView /** 當地圖顯示區域發生變化時觸發 */ - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{ [self showBussinessedInMapView]; } |
【5】二元運算子和引數之間要有一個空格,如賦值號=左右各留一個空格。
1 |
self.myString = @"235423rew523452345"; |
【6】一元運算子和引數之間不放置空格,比如!非運算子,&按位與,|按位或。
1 2 |
BOOL isOpen = true; BOOL isClose = !isOpen; |
【7】強制型別轉換和引數之間不放置空格。
1 |
NSString *str3 = (NSString*)self.myString; |
【8】長的變數值應該拆分為多行。尤其體現在使用陣列或者字典。以下也分別是快速宣告陣列@[]和字典@{}的方法。
1 2 3 4 5 6 7 8 9 |
NSArray *array = @[@"111", @"2222222222", @"3333333", @"wwwwwwwwwwww" ]; NSDictionary *dict = @{@"age":@"20", @"gender":@"female", @"isMarried":@"false" }; |
【9】儘量使用有意義的名字命名,拒絕使用i,j等無意義字元命名。類的命名首字母大寫,其他變數的命名首字元小寫,並使用駝峰式分割單詞。
【10】儘量減少在程式碼中直接使用數字常量,而使用巨集定義等方式。如:MAX_NUMBER_PHONE替代8等等。這樣我們搜尋也比較方便。
【11】儘量減少程式碼中的重複計算,比如程式碼中多處要使用螢幕寬度,然後計算:[[UIScreenmainScreen] bounds].size.width ,很多次,閒得很繁瑣,程式碼也冗長。不如直接巨集定義:
1 |
#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width) |
【12】合理使用約定俗成的縮略詞:
alloc:分配;
alt:輪流,交替;
app:應用程式;
calc:計算;
dealloc:銷燬、析構;
func:函式、方法;
horiz:水平的;
info:資訊;
init:初始化;
max:最大的;
min:最小的;
msg:訊息;
nib:Interface Builder;
rect:矩形;
temp:暫時的;
vert:垂直的;
【13】巨集定義全部字母大寫。
【14】函式長度不要超過50行,小函式比大函式可讀性更強。函式的引數不宜過多,零元函式最好,一元函式也不錯,高於三元的函式虛重構。
【15】合理範圍內使用鏈式程式設計:
1 |
NSString *myName = [[NSString alloc] init]; |
但是巢狀不宜超過3層,超過3層需進行重構。
【16】函式呼叫時所有引數在同一行。如果引數過多,則可以每行一個引數,每個引數以冒號對齊。
1 2 3 |
[[NSNotificationCenter defaultCenter] addObserver:activityIndicator selector:NSSelectorFromString(@"startActivity") name:SDWebImageDownloadStartNotification object:nil]; |
【17】對傳入引數的保護或者說是否為空的判斷,儘量不要使用if(!obj),而使用NSAssert斷言來處理。NSAssert是系統定義的巨集。
1 |
NSAssert(myName != nil, @"myName引數為空"); |
- 如果條件判斷為真,則程式繼續執行。
- 如果判斷條件為假,則丟擲異常,異常內容為後面定義的字串。
【18】方法引數名前一般使用”an”,”the”,”new”來進行修飾。如
1 |
-(void)setPersonInfo:(NSString*)theID theName:(NSString*)theName theAge:(NSInteger*)theAge |
【19】if-else超過四層的時候,就要考慮重構,多層的if-else結構很難維護。
【20】當需要一定條件才執行某項操作時,最左邊的應該是最重要的程式碼,不要將最重要的程式碼內嵌到if中。如良好的風格是:
1 2 3 4 5 6 7 |
- (void)someMethod { if(![someOther boolValue]) { return; } //最重要的程式碼寫在這裡; } ` |
反面教材
1 2 3 4 5 |
- (void)someMethod { if([someOther boolValue]) { //重要程式碼; } } |
【21】所有的邏輯塊都使用{}花括號包圍,就算只是一行程式碼。
【22】明確指定建構函式,並有適當的註釋。
【23】不要在init方法中把變數或者說屬性初始化為0或者nil,因為沒有必要。
【24】UIView的子類初始化的時候,不要進行任何的佈局操作。佈局操作應該在layoutSubviews裡面做;需要重新佈局的時候呼叫setNeedsLayout,而不要直接呼叫layoutSubviews。
【25】保持公共API簡單,也就是保持.h檔案簡單。放在.h中宣告的函式都是會被公開的,如果根本就沒必要對其他類公開,再不要在.h中宣告。OC中的方法都是公有方法,沒有私有方法一說。
【26】一個檔案只實現一個類。同一個檔案中不要有多個類。
【27】Protocol單獨用一個檔案來建立,儘量不要與相關類混在一個檔案中。
【28】在類定義中使用到自己定義類的時候,儘量不要在標頭檔案中引入自己定義類的標頭檔案,使用@class替代。而在實現檔案中引入標頭檔案。
【29】佈局時儘量使用相對佈局,比如使用子View在父View中的相對位置。
【30】程式碼摺疊,這個可能是關於開發效率的,我也寫在編碼規範中,因為這個很有用。Xcode7預設沒有開啟程式碼摺疊,如果你的方法體行數很長,看起來會很不方便,此時你就可以把方法“收起來”,一個類中的結構就會很清晰。開啟方法如下:Xcode選單–>Preferences–>Text Editing–>勾選Code folding ribbon.
【31】推薦方法的第一個花括號直接跟在方法體後,而不是另起一行,這樣可以減少程式碼行。
【32】推薦方法體中的第一行留空,最後一行不留空,這樣一個方法就會比較清晰。如下:
1 2 3 4 5 6 |
#pragma mark - 生命週期 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. } |
- 但是如果該花括號裡面又是一個if,for之類的帶花括號的語句塊,那麼上述的第一行可以不留空。
- 同樣,如果花括號內第一行是註釋的話,第一行也可以不留空。註釋也起到了分隔程式碼的作用,看起來比較清晰。
- 再者,如果花括號內只有一行程式碼,第一行可以不留空。
【33】block中第一行也要留空,同方法體中的第一行留空,使程式碼清晰。
1 2 3 4 5 6 7 8 |
[sheet setCallBackBlock:^(NSInteger index) { CGRect viewBounds = [ [UIScreen mainScreen] applicationFrame]; if (sheet.cancelButtonIndex == index) { } NSLog(@"%@",NSStringFromCGRect(viewBounds)); }]; |
【34】代表類方法和例項方法的”+”加號,”-“減號後需要一個空格。這是一個非常小的細節,系統預設的方法都是這樣的,我們自己宣告或者實現一個方法的時候也需要這樣
1 |
- (void)setCallBackBlock:(blockCallBack)block; |
【35】這一條有點像程式設計經驗了,就是為解決某個問題估算時間。比如要開發某個功能、除錯某個bug、給自己一個時間限制,如果在這期間不能解決問題,那麼就去尋求幫助。這既是給自己一個壓力,也為了不浪費時間。雖然,這一條其實很難做到,我往往由於不甘心而無限拖延時間去解決問題。
【36】由於提到程式設計經驗,就不得不提到版本控制。務必去學會SVN或者Git,就算你是獨立開發,也要學會控制自己的程式碼,當然,你要經常備份你的程式碼。
原文https://github.com/chenyufeng1991
上面都是個人總結的,並不一定是標準規範,如果大家的開發團隊或者公司有自己的編碼規範,當然按照團隊的來
個人見解:
1.關於【13】點,個人覺得還是要根據實際需求書寫,不一定完全寫成大寫,對於國人來說,小寫更便於閱讀,不過肯定不可以全小寫
比如SDWebImage中的巨集定義
1 |
#define UIImageViewHighlightedWebCacheOperationKey @"highlightedImage" |
2.關於【10】點,儘量減少在程式碼中直接使用數字常量,而使用巨集定義等方式;巨集定義太多會導致工程編譯速度變慢!個人感覺,如果多處用到一個數字,定義個巨集好一些,方便管理;如果只有一定地方用到,那就沒必要了,可以選擇常量
比如SDWebImage原始碼示例
1 2 3 4 5 6 7 8 |
static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week NSString *const SDWebImageErrorDomain = @"SDWebImageErrorDomain"; if (frameDuration < 0.011f) { frameDuration = 0.100f; } if (timeoutInterval == 0.0) { timeoutInterval = 15.0; } |
3.關於【33】點,進行擴充套件,@interface宣告屬性之間要空一格,即使只有一個屬性,
SDWebImage原始碼示例:
1 2 3 4 5 6 7 8 9 10 |
@interface宣告屬性之間要空一格,計算只有一個屬性, SDWebImage原始碼示例: @interface SDWebImageDownloader () @property (strong, nonatomic) NSOperationQueue *downloadQueue; @property (strong, nonatomic) NSMutableDictionary *URLCallbacks; @property (strong, nonatomic) NSMutableDictionary *HTTPHeaders; // This queue is used to serialize the handling of the network responses of all the download operation in a single queue @property (SDDispatchQueueSetterSementics, nonatomic) dispatch_queue_t barrierQueue; @end |
4.關於【4】點,進行擴充套件,宣告屬性,如果屬性比較多,可對屬性進行分類,方便檢視
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
註釋樣式 /* *********************************************************************** * * ??? 當你疼的時候,你才會開始真正的行動 ??? * 人類的大腦是很貪心的,總是想同時幹很多事情 * 我們又很著急,總想在比較短的時間見效; * 大多數人失敗並非個人能力不行 * 而是因為他們將精力分散在太多的目標上面了; *********************************************************************** */ // >>>>>>>>>>>>>>>>>>>>>>>>>> 資料來源介面 /** 本地圖片陣列 */ @property (nonatomic, strong) NSArray *localizationImageNamesGroup; /** 網路圖片 url string 陣列 */ @property (nonatomic, strong) NSArray *imageURLStringsGroup; /** 每張圖片對應要顯示的文字陣列 */ @property (nonatomic, strong) NSArray *titlesGroup; // >>>>>>>>>>>>>>>>>>>>>>>>> 滾動控制介面 /** 自動滾動間隔時間,預設2s */ @property (nonatomic, assign) CGFloat autoScrollTimeInterval; /** 是否無限迴圈,預設Yes */ @property(nonatomic,assign) BOOL infiniteLoop; // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 自定義樣式介面 /** 輪播圖片的ContentMode,預設為 UIViewContentModeScaleToFill */ @property (nonatomic, assign) UIViewContentMode bannerImageViewContentMode; /** 佔點陣圖,用於網路未載入到圖片時 */ @property (nonatomic, strong) UIImage *placeholderImage; |