1. 程式人生 > >iOS 開發編碼建議與程式設計經驗

iOS 開發編碼建議與程式設計經驗

在開發過程中,我們不僅要去看別人的程式碼,也要讓別人看我們的程式碼。那麼,有一個良好的編碼習慣將會非常重要。下面將會羅列使用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 來快速查詢方法的位置。



#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]; 

#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】二元運算子和引數之間要有一個空格,如賦值號=左右各留一個空格。



self.myString = @"235423rew523452345"; 
self.myString = @"235423rew523452345";

【6】一元運算子和引數之間不放置空格,比如!非運算子,&;按位與,|按位或。



BOOL isOpen = true; 
BOOL isClose = !isOpen; 
BOOL isOpen = true;BOOL isClose = !isOpen;

【7】強制型別轉換和引數之間不放置空格。



NSString *str3 = (NSString*)self.myString; 
NSString *str3 = (NSString*)self.myString;

【8】長的變數值應該拆分為多行。尤其體現在使用陣列或者字典。以下也分別是快速宣告陣列@[]和字典@{}的方法。



NSArray *array = @[@"111", 
@"2222222222", 
@"3333333", 
@"wwwwwwwwwwww" 
]; 
NSDictionary *dict = @{@"age":@"20", 
@"gender":@"female", 
@"isMarried":@"false" 
}; 
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 ,很多次,閒得很繁瑣,程式碼也冗長。不如直接巨集定義:



#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width) 
#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】合理範圍內使用鏈式程式設計:



NSString *myName = [[NSString alloc] init]; 
NSString *myName = [[NSString alloc] init];

但是巢狀不宜超過3層,超過3層需進行重構。

 

【16】函式呼叫時所有引數在同一行。如果引數過多,則可以每行一個引數,每個引數以冒號對齊。



[[NSNotificationCenter defaultCenter] addObserver:activityIndicator 
selector:NSSelectorFromString(@"startActivity") 
name:SDWebImageDownloadStartNotification object:nil]; 
[[NSNotificationCenter defaultCenter] addObserver:activityIndicator selector:NSSelectorFromString(@"startActivity") name:SDWebImageDownloadStartNotification object:nil];

【17】對傳入引數的保護或者說是否為空的判斷,儘量不要使用if(!obj),而使用NSAssert斷言來處理。NSAssert是系統定義的巨集。



NSAssert(myName != nil, @"myName引數為空"); 
NSAssert(myName != nil, @"myName引數為空");如果條件判斷為真,則程式繼續執行。 
如果判斷條件為假,則丟擲異常,異常內容為後面定義的字串。

【18】方法引數名前一般使用”an”,”the”,”new”來進行修飾。如



-(void)setPersonInfo:(NSString*)theID theName:(NSString*)theName theAge:(NSInteger*)theAge 
-(void)setPersonInfo:(NSString*)theID theName:(NSString*)theName theAge:(NSInteger*)theAge

【19】if-else超過四層的時候,就要考慮重構,多層的if-else結構很難維護。

 

【20】當需要一定條件才執行某項操作時,最左邊的應該是最重要的程式碼,不要將最重要的程式碼內嵌到if中。如良好的風格是:



- (void)someMethod { 
if(![someOther boolValue]) { 
return; 

//最重要的程式碼寫在這裡; 


- (void)someMethod {if(![someOther boolValue]) { return;}//最重要的程式碼寫在這裡;}`

反面教材



- (void)someMethod { 
if([someOther boolValue]) { 
//重要程式碼; 


- (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】推薦方法體中的第一行留空,最後一行不留空,這樣一個方法就會比較清晰。如下:



#pragma mark - 生命週期 
- (void)viewDidLoad {[super viewDidLoad]; 
// Do any additional setup after loading the view. 

#pragma mark - 生命週期- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.}但是如果該花括號裡面又是一個if,for之類的帶花括號的語句塊,那麼上述的第一行可以不留空。 
同樣,如果花括號內第一行是註釋的話,第一行也可以不留空。註釋也起到了分隔程式碼的作用,看起來比較清晰。 
再者,如果花括號內只有一行程式碼,第一行可以不留空。

【33】block中第一行也要留空,同方法體中的第一行留空,使程式碼清晰。



[sheet setCallBackBlock:^(NSInteger index) {CGRect viewBounds = [ [UIScreen mainScreen] applicationFrame]; 
if (sheet.cancelButtonIndex == index) {} 
NSLog(@"%@",NSStringFromCGRect(viewBounds)); 
}]; 
[sheet setCallBackBlock:^(NSInteger index) {CGRect viewBounds = [ [UIScreen mainScreen] applicationFrame];if (sheet.cancelButtonIndex == index) {}NSLog(@"%@",NSStringFromCGRect(viewBounds));}];

【34】代表類方法和例項方法的”+”加號,”-“減號後需要一個空格。這是一個非常小的細節,系統預設的方法都是這樣的,我們自己宣告或者實現一個方法的時候也需要這樣



- (void)setCallBackBlock:(blockCallBack)block; 
- (void)setCallBackBlock:(blockCallBack)block;

【35】這一條有點像程式設計經驗了,就是為解決某個問題估算時間。比如要開發某個功能、除錯某個bug、給自己一個時間限制,如果在這期間不能解決問題,那麼就去尋求幫助。這既是給自己一個壓力,也為了不浪費時間。雖然,這一條其實很難做到,我往往由於不甘心而無限拖延時間去解決問題。

 

【36】由於提到程式設計經驗,就不得不提到版本控制。務必去學會SVN或者Git,就算你是獨立開發,也要學會控制自己的程式碼,當然,你要經常備份你的程式碼。

 

原文https://github.com/chenyufeng1991

上面都是個人總結的,並不一定是標準規範,如果大家的開發團隊或者公司有自己的編碼規範,當然按照團隊的來


個人見解: 

1.關於【13】點,個人覺得還是要根據實際需求書寫,不一定完全寫成大寫,對於國人來說,小寫更便於閱讀,不過肯定不可以全小寫

比如SDWebImage中的巨集定義



#define UIImageViewHighlightedWebCacheOperationKey @"highlightedImage"
#define UIImageViewHighlightedWebCacheOperationKey @"highlightedImage"

2.關於【10】點,儘量減少在程式碼中直接使用數字常量,而使用巨集定義等方式;巨集定義太多會導致工程編譯速度變慢!個人感覺,如果多處用到一個數字,定義個巨集好一些,方便管理;如果只有一定地方用到,那就沒必要了,可以選擇常量

 

比如SDWebImage原始碼示例



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; 

static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 weekNSString *const SDWebImageErrorDomain = @"SDWebImageErrorDomain";if (frameDuration < 0.011f) {frameDuration = 0.100f;}if (timeoutInterval == 0.0) {timeoutInterval = 15.0;}

3.關於【33】點,進行擴充套件,@interface宣告屬性之間要空一格,即使只有一個屬性,

SDWebImage原始碼示例:



@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 
@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[email protected] (SDDispatchQueueSetterSementics, nonatomic) dispatch_queue_t barrierQueue;@end

4.關於【4】點,進行擴充套件,宣告屬性,如果屬性比較多,可對屬性進行分類,方便檢視