運(yùn)算符
- 一元運(yùn)算符與變量之間沒有空格
!bValue
~iValue
++iCount
*strSource
&fSum
- 二元運(yùn)算符與變量之間必須有空格
fWidth = 5 + 5;
fLength = fWidth * 2;
fHeight = fWidth + fLength;
for(int i = 0; i < 10; i++)
變量
1.變量名必須使用駝峰格式,自定義類,協(xié)議使用大駝峰
SFHomePageViewController
2.對(duì)象等局部變量使用小駝峰
NSString *personName = @"";
3.變量的名稱必須同時(shí)包含功能與類型
UIButton *addButton //添加按鈕
UILabel *nameLabel //名字標(biāo)簽
NSArray *nameArray //名字?jǐn)?shù)組
NSDictionary *productDict //產(chǎn)品字典
常量
1.常量以相關(guān)類名作為前綴
static const NSTimeInterval YZDLoginAnimateViewFadeOutTime = 0.4;
2.對(duì)外公開某個(gè)常量,如通知
//.h文件
extern NSString *const YZDLoginOutNotification;
//.m文件
static NSString * const YZDLoginOutNotification = @"YZDLoginOutNotification";
枚舉
- 使用NS_ENUM進(jìn)行定義
- 對(duì)于一些狀態(tài) 選項(xiàng)的使用枚舉
盡量少用根據(jù)數(shù)字判斷狀態(tài)少用字符串 數(shù)字判斷狀態(tài)
typedef NS_ENUM(NSInteger, DQGameInfoDisplayType) {
DQGameInfoDisplayTypeDefault = 0,
DQGameInfoDisplayTypeMatch = 1, //比賽
DQGameInfoDisplayTypeEvent = 2, //對(duì)應(yīng)節(jié)目
};
宏
- 宏、常量名都要使用大寫字母,用下劃線‘_’分割單詞
#define URL_GAIN_QUOTE_LIST @"/v1/quote/list"
#define URL_UPDATE_QUOTE_LIST @"/v1/quote/update"
#define URL_LOGIN @"/v1/user/login”
- 宏定義中如果包含表達(dá)式或變量盾致,表達(dá)式和變量必須用小括號(hào)括起來
#define MY_MIN(A, B) ((A)>(B)?(B):(A))
- 開頭用k標(biāo)識(shí),比如Cell的重用字符荣暮,k+cell的名稱+identifier
#define kGBHomeItemTableViewCellIdentifier = @"kGBHomeItemTableViewCellIdentifier"
屬性
- 屬性的關(guān)鍵字推薦按照原子性庭惜,讀寫,內(nèi)存管理的順序排列
@property (nonatomic, readwrite, copy) NSString *name;
@property (nonatomic, readwrite, strong) UIView *headerView;
方法
- 方法名中不應(yīng)使用and渠驼,而且簽名要與對(duì)應(yīng)的參數(shù)名保持高度一致
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height;
- 方法實(shí)現(xiàn)時(shí)蜈块,如果參數(shù)過長(zhǎng)鉴腻,則令每個(gè)參數(shù)占用一行,以冒號(hào)對(duì)齊
- (void)doSomethingWithFoo:(NSString *)theFoo
rect:(CGRect)theRect
interval:(CGFloat)theInterval {
//Implementation
}
- 大括號(hào)開始與行尾
void function(param1,param2) {
}
類
- 類文件名要見名知意
- Model類名以Model結(jié)尾
YZDUserModel
- 自定義視圖命名以View結(jié)尾
YZDTabIndexHeaderView
- 視圖控制器命名以ViewController結(jié)尾
YZDTabIndexViewController
- init && dealloc
// 將 dealloc 方法放在實(shí)現(xiàn)文件的最前面
- (void)dealloc {
// 釋放注冊(cè)的通知和KVO的監(jiān)聽
}
- (instancetype)init {
self = [super init]; // call the designated initializer
if (self) {
// Custom initialization
}
return self;
}
- 類的頭文件中盡量少引用其他頭文件
有時(shí)百揭,類A需要將類B的實(shí)例變量作為它公共API的屬性爽哎。這個(gè)時(shí)候,我們不應(yīng)該引入類B的頭文件器一,而應(yīng)該使用向前聲明(forward declaring)使用class關(guān)鍵字课锌,并且在A的實(shí)現(xiàn)文件引用B的頭文件。祈秕,這么做的優(yōu)點(diǎn):
- 不在A的頭文件中引入B的頭文件渺贤,就不會(huì)一并引入B的全部?jī)?nèi)容,這樣就減少了編譯時(shí)間请毛。
- 可以避免循環(huán)引用:因?yàn)槿绻麅蓚€(gè)類在自己的頭文件中都引入了對(duì)方的頭文件志鞍,那么就會(huì)導(dǎo)致其中一個(gè)類無法被正確編譯。
// EOCPerson.h
#import
@class EOCEmployer;
@interface EOCPerson : NSObject
@property (nonatomic, copy) NSString *firstName;
@property (nonatomic, copy) NSString *lastName;
@property (nonatomic, strong) EOCEmployer *employer;//將EOCEmployer作為屬性
@end
// EOCPerson.m
#import "EOCEmployer.h"
但是個(gè)別的時(shí)候方仿,必須在頭文件中引入其他類的頭文件:
主要有兩種情況:
- 該類繼承于某個(gè)類固棚,則應(yīng)該引入父類的頭文件。
- 該類遵從某個(gè)協(xié)議仙蚜,則應(yīng)該引入該協(xié)議的頭文件此洲。而且最好將協(xié)議單獨(dú)放在一個(gè)頭文件中
- 頭文件.h
- 方法的參數(shù)在一排顯示
- 方法之間保留一行
- 第一個(gè)方法和property保留空行
- 最后一個(gè)方法和@end保留空行
@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, copy) NSString *name;
- (void)testName;
- (void)testAge;
@end
- 實(shí)現(xiàn)文件.m
- 引用頭文件的順序
#import <AVFoundation/AVFoundation.h>
#import <Mantle/Mantle.h>
#import "SFUserStatus.h"
- 類的布局順序
- (void)dealloc
#pragma mark - Life Cycle Methods
#pragma mark - Override Methods
#pragma mark - Network Methods
#pragma mark - Target Methods
#pragma mark - Public Methods
#pragma mark - Private Methods
#pragma mark - Delegate
#pragma mark - Lazy Loads
分類
- 分類添加的方法需要添加前綴和下劃線
@interface NSMutableDictionary (DQSafetyCheck)
/**
* 空值保護(hù) key,value為空時(shí)防止crash
*
* @param anObject object
* @param aKey key
*/
- (void)dq_setSafeObject:(id)anObject forKey:(id)aKey;
@end
if語(yǔ)句
- 必須列出所有分支(窮舉所有的情況),而且每個(gè)分支都必須給出明確的結(jié)果委粉。推薦這樣寫
var hintStr;
if (count < 3) {
hintStr = "Good";
} else {
hintStr = "";
}
不推薦這樣寫
var hintStr;
if (count < 3) {
hintStr = "Good";
}
- 不要使用過多的分支呜师,要善于使用return來提前返回錯(cuò)誤的情況
推薦這樣寫:
- (void)someMethod {
if (!goodCondition) {
return;
}
//Do something
}
不推薦這樣寫:
- (void)someMethod {
if (goodCondition) {
//Do something
}
}
- 條件過多,過長(zhǎng)的時(shí)候應(yīng)該換行
if (condition1() &&
condition2() &&
condition3() &&
condition4()) {
// Do something
}
Switch語(yǔ)句
- 每個(gè)分支都必須用大括號(hào)括起來贾节,每個(gè)case都要添加break關(guān)鍵字汁汗,避免出現(xiàn)fall-through
switch (integer) {
case 1: {
// ...
break;
}
case 2: {
// ...
break;
}
case 3: {
// ...
break;
}
default: {
// ...
break;
}
}
- 使用枚舉類型時(shí),不能有default分支栗涂, 除了使用枚舉類型以外碰酝,都必須有default分支
RWTLeftMenuTopItemType menuType = RWTLeftMenuTopItemMain;
switch (menuType) {
case RWTLeftMenuTopItemMain: {
// ...
break;
}
case RWTLeftMenuTopItemShows: {
// ...
break;
}
case RWTLeftMenuTopItemSchedule: {
// ...
break;
}
}
函數(shù)
- 一個(gè)函數(shù)的長(zhǎng)度不要太長(zhǎng)
- 一個(gè)函數(shù)只做一件事(單一原則)
- 對(duì)于有返回值的函數(shù)(方法),每一個(gè)分支都必須有返回值
int function() {
if (condition1) {
return count1
} else if (condition2) {
return count2
} else {
return defaultCount
}
}
- 對(duì)輸入?yún)?shù)的正確性和有效性進(jìn)行檢查戴差,參數(shù)錯(cuò)誤立即返回
void function(param1,param2) {
if (param1 is unavailable) {
return;
}
if (param2 is unavailable) {
return;
}
//Do some right thing
}
代理、block
- 代理铛嘱,合理的使用optional暖释,required關(guān)鍵字
- 向代理、block發(fā)送消息時(shí)需要判斷其是否實(shí)現(xiàn)該方法
if ([self.delegate respondsToSelector:@selector(signUpViewControllerDidPressSignUpButton:)]) {
[self.delegate signUpViewControllerDidPressSignUpButton:self];
}
字符串墨吓、數(shù)組球匕、字典
取值一定要注意類型、非空帖烘、越界等的判斷亮曹,防止崩潰等問題
- 字符串
//判斷字符串是否是字符串,是否是null,一般從網(wǎng)絡(luò)獲取
static inline BOOL verifiedString(id strlike) {
if (strlike && ![strlike isEqual:[NSNull null]] && [[strlike class] isSubclassOfClass:[NSString class]] && ((NSString *) strlike).length > 0) {
return YES;
} else {
return NO;
}
}
// 用法
if (verifiedString(urlString)) {
// dosomething
}
- 數(shù)組
//判斷是否是有效數(shù)組照卦,一般從網(wǎng)絡(luò)獲取
static inline BOOL verifiedNSArray(id arraylike) {
if (arraylike && ![arraylike isEqual:[NSNull null]] && [[arraylike class] isSubclassOfClass:[NSArray class]] && [arraylike count] > 0) {
return YES;
} else {
return NO;
}
}
// 用法:數(shù)組類型 && 未越界
if (verifiedNSArray(self.dataArray) && indexPath.row < self.dataArray.count) {
}
- 字典
// 判斷是否是字典式矫,一般從網(wǎng)絡(luò)獲取
static inline BOOL verifiedNSDictionary(id dictlike) {
if (dictlike && ![dictlike isEqual:[NSNull null]] && [[dictlike class] isSubclassOfClass:[NSDictionary class]]) {
return YES;
} else {
return NO;
}
}
// 用法:數(shù)據(jù)的解析
if (verifiedNSDictionary(responseObject)) {
}
注釋
優(yōu)秀的代碼大部分是可以自描述的,我們完全可以用程代碼本身來表達(dá)它到底在干什么役耕,而不需要注釋的輔助采转。
但并不是說一定不能寫注釋,有以下四種情況比較適合寫注釋:
公共接口(注釋要告訴閱讀代碼的人瞬痘,當(dāng)前類能實(shí)現(xiàn)什么功能)故慈。
涉及到比較深層專業(yè)知識(shí)的代碼(注釋要體現(xiàn)出實(shí)現(xiàn)原理和思想)。
容易產(chǎn)生歧義的代碼(但是嚴(yán)格來說框全,容易讓人產(chǎn)生歧義的代碼是不允許存在的)察绷。
踩過坑的代碼(如特定機(jī)型系統(tǒng)會(huì)崩潰之類的代碼,如有解決方案或鏈接附上最佳)津辩。
- Class注釋
/**
Gif集錦拆撼,中間Gif視圖
*/
@interface DQGifCollectionGifView : UIView
@end
- property注釋
@interface DeliveryModel : NSObject
/// 提貨劵所在商圈id
@property (nonatomic, assign) long long mallId;
/// 商圈全稱
@property (nonatomic, copy) NSString *mallFullName;
/// 商圈簡(jiǎn)稱
@property (nonatomic, copy) NSString *mallShortName;
/// 提貨劵號(hào)
@property (nonatomic, copy) NSString *credentialsCode;
/// 總金額
@property (nonatomic, assign) NSInteger totalAmount;
- 方法注釋
/**
* 圈子列表(達(dá)人榜/置頂/貼子列表)
*
* @param urlStr 請(qǐng)求URLStr
* @param params 參數(shù)
* @param block 返回的結(jié)果和code
*/
- (void)getCircleRefreshHeadListWithUrl:(NSString *)urlStr params:(NSDictionary *)params resultBackBlock:(DQAnalyzeBackBlock)block;
參考文獻(xiàn)