帶出幾十位從零開始學iOS的實習生或試用期的開發人員後,以爲真的是千人千面,每一個人寫的代碼都風格迥異,若是沒有一個文檔規範,每次都和新人進行口頭的說教,大概本身是不用敲代碼了,因此吃了虧了就開始編寫iOS的編程規範。因爲本人在寫iOS代碼前一直是C語言的開發,因此不少規範都受C語言的影響。c++
與你們分享下我總結的編程規範,有不合適的請你們指出(最好能舉例說明爲什麼很差,並給一個好的推薦)^_^編程
軟件的生命週期貫穿產品的開發,測試,生產,用戶使用,版本升級和後期維護等過程,只有易讀,易維護的軟件代碼才具備生命力。數組
簡單是最美。不要過度追求技巧,不然會下降程序的可讀性。安全
編程首先考慮的是知足正確性,健壯性,可維護性,可移植性等質量因素。bash
不能夠測試的代碼是沒法保障質量的。實現設計功能的同時,要提供能夠測試、驗證的方法。服務器
方法是一個處理單元,是由特定功能的,因此應該很好地規劃方法,不能是全部東西都放在一個方法裏實現。app
當代碼有改動時,註釋必定要修改,而且不要添加多餘或重複的註釋。框架
程序佈局的目的是現實出程序良好的邏輯結構,提升程序的準確性、連續性、可讀性、可維護性。統一的程序佈局和編程風格,有助於提升整個項目的開發質量,提升開發效率,下降開發成本。異步
遵循統一的佈局順序書寫頭文件和實現文件:ide
文件頭註釋 #import 文件內部使用的宏 常量定義 文件內部使用的數據類型 全局變量 本地變量 類定義/實現
「{」前面添加一個空格,緊跟語句後。方法(函數)時,「{」另起一行並獨 佔一行書寫。
if ( numberA > numberB ) {
return numberA;
}
複製代碼
NSString *str1 = @"Hello World!";
複製代碼
CGFloat fWidth;
CGFloat fLength;
CGFloat fHeight;
複製代碼
在Xcode->Preferences->Text Editing->Indentation->Prefer indent using中,將值設置爲Spaces。
- (void)dealloc
{
// Do Something
}
if (isUpdated) {
// Do Something
}
複製代碼
promotionsEntity.promotionImageStr = activityItemDict[@"promotion_image"];
promotionsEntity.promotionIdNum = activityItemDict[@"promotion_id"];
promotionsEntity.promotionNameStr = activityItemDict[@"promotion_name"];
promotionsEntity.promotionColorStr = activityItemDict[@"promotion_color"];
複製代碼
!bValue
~iValue
++iCount
*strSource
&fSum
複製代碼
fWidth = 5 + 5;
fLength = fWidth * 2;
fHeight = fWidth + fLength;
複製代碼
if、for、while等關鍵字以後應留一個空格再跟左括號」(」。
if (0 == fWidth)
複製代碼
方法名後緊跟」:」,而後緊跟形參,返回類型」(」與」-」之間有一個空格。
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
複製代碼
/* 設置Frame的值 */
// TO DO
複製代碼
if ( 0 == fWidth
|| 0 < fLength )
複製代碼
- (void)didReceiveMemoryWarning
複製代碼
#pragma mark – UITextFieldDelegate
複製代碼
- (void)doSomethingWith:(NSString *)theFoo
rect:(CGRect)theRect
interval:(CGFloat)theInterval
{
複製代碼
若是方法名比參數名短,則每一個參數佔用一行,至少縮進4個字符,且爲垂直對齊(非冒號對齊)。
- (void)short:(NSString *)theFoot
longKeyword:(CGRect)theRect
evenLongerkeyword:(float)theInterval
{
}
複製代碼
在同一行
[self doSomethingWith:@"test" rect:self.view.frame interval:1.0f];
複製代碼
或 冒號對齊
[self doSomethingWith:@"test"
rect:self.view.frame
interval:1.0f];
複製代碼
id<MyProtocalDelegate> delegate;
複製代碼
在類聲明中包含多個protocal,每一個protocal佔用一行,縮進2個字符。
@interface CustomBackButtonViewController () <UITextFieldDelegate,
MyProtocalDelegate,
UITabBarControllerDelegate,
UITabBarDelegate>
複製代碼
也能夠與第一個對齊,保持清晰易讀
@interface ShopViewController () <UIGestureRecognizerDelegate,
HXSClickEventDelegate,
UITableViewDelegate,
UITableViewDataSource>
複製代碼
若是並不是全部方法都是必須得,使用@optional標示。
#import 「LocationCustomButton.h」
最開始是導入須要使用到的其餘class頭文件,頭文件按類型分類
// controller
#import 「TextSelectionViewController.h"
// model
#import "PayPasswordUpdateModel.h"
#import "WalletModel.h"
// views
#import "PayPasswordAlertView.h"
複製代碼
#define KEY_BANK_TAIL @「bank_tail"
添加宏定義,將在文件中須要使用到的常量,字符串等用宏定義。
@property (nonatomic, strong) NSArray *bankCardList;
property的屬性定義。不用將須要使用的methods聲明,在iOS7後Methods已經不須要先聲明再使用了。
- (void)viewDidLoad
#pragma mark - Life Cycle
添加生命週期的方法
- (void)viewWillAppear:(BOOL)animated
- (void)viewDidAppear:(BOOL)animated
- (void)viewWillDisappear:(BOOL)animated
-(void)viewDidDisappear:(BOOL)animated
- (void)didReceiveMemoryWarning
- (void)dealloc
複製代碼
#pragma mark - override
重載父類的方法
#pragma mark - Intial Methods
初始化的方法,如
- (void)initialNavigationBar
- (void)initialTableView
複製代碼
#pragma mark - Target Methods
點擊事件或通知事件
#pragma mark - UITextFieldDelegate
Delegate的事件,將全部的delegate放在同一個pragma下
#pragma mark - Setter Getter Methods
全部的property使用懶加載,並將setter或getter放在底部,不影響業務代碼的閱讀。
#pragma mark - private method
私有方法的代碼儘可能抽取建立公共class。
註釋語言不宜太多也不能太少,註釋語言必須準確、易懂、簡潔。
//
// ViewController.m
// test
//
// Created by ArthurWang on 14-5-7.
// Copyright (c) 2014年 Insigma HengTian Software Ltd. All rights reserved.
//
複製代碼
/*
@class HTServerDatamanager
@abstract 異步鏈接服務器管理類
@discussion 異步請求服務器,接收到響應後,經過回調把數據回傳到對象
*/
複製代碼
/*
@method initWithTarget:selector:
@abstract 類初始化函數
@discussion 本類使用時必須調用此函數進行初始化
@param target 響應回調對象
@param selector 回調對象的selector
@result 類對象
*/
複製代碼
標識符應當直觀且能夠拼讀,可望文知意,英文單詞通常不要太複雜,用詞應當準確。
CGFloat variable__name;
NSString *variale___name;
複製代碼
NSString *contentOfView;
NSString *ContentOfView;
複製代碼
#define URL_GAIN_QUOTE_LIST @"/v1/quote/list"
#define URL_UPDATE_QUOTE_LIST @"/v1/quote/update"
#define URL_LOGIN @"/v1/user/login」
複製代碼
儘管局部變量和全局變量的做用域不一樣而不會發生語法錯誤,但容易令人誤解。
g_ 全局變量 s_ 模塊內靜態變量
方法名力求清晰、明瞭、經過方法名就可以判斷方法的主要功能。方法名中不一樣意義字段之間不要用下劃線鏈接,而要把每一個字段的首字母大寫以示區分。
- (NSString *)descriptionWithLocale:(id)locale;
複製代碼
不在類聲明和實現的「{」與「}」之間聲明。
@interface LumberjackViewController ()
{
NSArray *dataSource; // 錯誤:
}
複製代碼
變量、常量和數據類型是程序編寫的基礎,是直接關係到程序設計的成敗。
一個變量只用來表示一個特定功能,不要把一個變量做多種用途。
錯誤: if ( 100 > (fWidth = 50 * fLength) )
#define MY_MIN(A, B) ((A)>(B)?(B):(A))
複製代碼
UIViewController: VC UIImage: Img
UIImageView:ImagView 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
複製代碼
在ARC中NSString的使用Strong與Copy的效果同樣。
NSArray<NSString *> *testArr = [NSArray arrayWithObjects:@"Hello", @"world", nil];
NSDictionary<NSString *, NSNumber *> *dic = @{@"key":@(1), @"age":@(10)};
複製代碼
在* 符號前面都添加一空格。
表達式是語句的一部分,他們是不可分割的。
複雜的語句閱讀起來,難於理解,並容易隱含錯誤。
因爲將運算符的優先級與結合律熟記是比較困難的,爲了防止產生歧義並提升可讀性,即便不加括號時運算順序不會改變,也應當用括號肯定表達式的操做順序。
if ( (( 0 == iYear%4 ) && ( 0 != iYear%100 )) || ( 0 == iYear%400 ) )
複製代碼
錯誤:int iResult = iYear++-++iMonth+iDay++;
if (isSuccess) //真
if (!isSuccess) //假
複製代碼
if (0 == iYear)
if ( 0 != iMonth )
複製代碼
指針變量的零值是「空」(即nil),nil的值與0相同,可是二者含義不一樣。
if ( nil == strName )
複製代碼
避免漏掉break語句形成程序錯誤,同時保持程序簡潔。對於多個分支相同處理的狀況能夠共用一個break,可是要用註釋加以說明。
這樣作更能適應數組的特色,數組的下標屬於一個「半開半閉區間」。
int iMax[1000];
for (int i = 0; i < 1000; i++)
{
NSLog(@"%d", iMax[i]);
}
複製代碼
一個方法一個功能。
若是參數的確比較多,不妨把這些參數定義成一個結構(或一個類)。
爲了保證對被調用函數返回值的判斷,有返回值的函數中都每個退出點都須要有返回值。
不少程序錯誤和崩潰是由非法參數引發的。
將函數的參數做爲工做變量,有可能錯誤地改變參數內容。對必須改變的參數,最好先用局部變量代之,最後再將該局部變量的內容賦給該參數。
冗長的函數不利於調試,可讀性差。
這樣有利於review代碼。 若是dealloc中調用其餘方法來release變量,將被release的變量以註釋的形式標註清楚。 先release自身成員變量,再調用父類dealloc方法。
@class MyViewController;
@interface ViewController : UIViewController
{
MyViewController *_myViewController;
}
複製代碼
爲保證代碼的可靠性,編程時請遵循以下基本原則,優先級遞減: 正確性 穩定性 可測試性 規範/可讀性 全局效率 局部效率 我的表達方式/我的方便性
內存操做主要是指對數組、指針、內存地址等得操做,內存操做越界是軟件系統主要錯誤之一,後果每每很是嚴重,引發崩潰。
避免由於野指針引發的程序崩潰。
引用未初始化的變量,會引發程序的崩潰。
經過複雜的邏輯或算術操做後,指針的位置就很難肯定。
強制類型轉化若是類型強轉錯誤會引發崩潰。
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
複製代碼
@interface ViewController ()
- (void)login;
@end
複製代碼
斷言是對某種假設條件進行檢查,能夠快速發現並定位軟件文件,同時對系統錯誤進行自動報警。
assert(str);
加快軟件運行速度。
應該都使用宏定義,採用當即數不容易理解含義並容易出錯。
應該考慮多語言國際化,儘可能使用NSLocalizedStringFromTable實現對字符串ID的引用。
由於retain會引發致使循環索引致使內存泄露,而且對類型的內存泄露沒法被Instrument發現,極難調試。
不要在View相關的類中添加過多的業務邏輯代碼,這讓代碼的可重用性不好。Controller負責業務邏輯代碼,且Controller的代碼與View儘可能無關。
// END
總結寫完了,複製黏貼好累啊。發現不少條在開發中都沒有遵照,由於需求變更實在太頻繁了,而且要求的開發時間實在過短。吐槽下產品組,能不能多考慮多考慮而後聽聽咱們開發的意見啊。!_!