方法聲明與定義:
1.星號前統(tǒng)一要求需要輸入空格
2.方法體左大括號于方法名的右側(cè)
3.-或者+與返回類型之間需要有空格。參數(shù)列表中,只有參數(shù)之間有空格。
-?(void)doSomethingWithString:(NSString?*)theString?{
...
}
如果一行有非常多的參數(shù),更好的方式是將每個(gè)參數(shù)單獨(dú)拆成一行。如果使用多行涡拘,將每個(gè)參數(shù)前的冒號對齊。
-?(void)doSomethingWith:(GTMFoo?*)theFoo
rect:(NSRect)theRect
interval:(float)theInterval?{
...
}
協(xié)議:
尖括號所包括的協(xié)議名稱與前面的類型標(biāo)識之間不應(yīng)該有空格
@interface?MyProtocoledClass?:?NSObject?{
@private?id?delegate;
}
方法名:
方法名應(yīng)該讀起來就像句子据德,這表示你應(yīng)該選擇與方法名連在一起讀起來通順的參數(shù)名鳄乏。
convertPoint:fromRect:
replaceCharactersInRange:withString:
訪問器方法應(yīng)該與他們getting的的成員變量的名字一樣,但不應(yīng)該以get作為前綴棘利。
例如:
-?(id)getDelegate;??//?AVOID
-?(id)delegate;?????//?GOOD
變量名:
要為變量起一個(gè)描述性的名字橱野。不要擔(dān)心浪費(fèi)列寬,若包含兩個(gè)以上單詞的命名應(yīng)該使用駝峰命名方式善玫,因?yàn)樽屝碌拇a閱讀者立即理解你的代碼更重要水援。
錯(cuò)誤的命名:
int?w;
int?nerr;
int?nCompConns;
UIButton*settingsButton;
tix?=?[[NSMutableArray?alloc]?init];
obj?=?[someObject?object];
p?=?[network?port];
正確的命名:
int?numErrors;
int?numCompletedConnections;
tickets?=?[[NSMutableArray?alloc]?init];
userInfo?=?[someObject?object];
port?=?[network?port];
星號應(yīng)緊貼變量名稱表示指向變量的指針,比如:
正確用法:
NSString *text;
不當(dāng)用法:
NSString* text;
NSString * text;
方法調(diào)用:
方法調(diào)用時(shí)茅郎,所有參數(shù)應(yīng)該在同一行
[myObject?doFooWith:arg1?name:arg2?error:arg3];
或者每行一個(gè)參數(shù)蜗元,以冒號對齊
[myObject?doFooWith:arg1
name:arg2
error:arg3];
[UIViewanimateWithDuration:1.0
animations:^{
// something
}
completion:^(BOOL?finished) {
// something
}];
異常:
每個(gè)@標(biāo)簽應(yīng)該有獨(dú)立的一行,在@與{}之間需要有一個(gè)空格系冗。@catch與被捕捉到的異常對象的聲明之間也要有一個(gè)空格奕扣。
@try?{
foo();
}
@catch?(NSException?*ex)?{
bar(ex);
}
@finally?{
baz();
}
條件語句的編寫:
1.為避免錯(cuò)誤,條件語句體必須使用大括號掌敬,即便語句體中的語句可以不必使用大括號(比如只有一行語句)成畦。常見的錯(cuò)誤包括在不使用大括號的情況下添加第二行語句,以為它屬于if語句的一部分涝开。此外,更可怕的事情是框仔,如果條件語句中的代碼行被注釋舀武,則本不術(shù)語條件語句的下一行代碼將變成條件語句的一部分。此外离斩,這種編碼風(fēng)格和所有其它條件語句均保持一致.
例如:
恰當(dāng)用法:
if(!error) {
returnsuccess;
}
不當(dāng)用法:
if(!error)
returnsuccess;
不當(dāng)用法2:
if(!error)returnsuccess;
2. 編寫括號內(nèi)的判斷語句時(shí)银舱,為避免手誤演變成賦值操作,一般將常量或nil放置在左邊
例如:
if(nil == self.dataList)?{
}
if(0 == theCount) {
}
Case語句
除非編譯器強(qiáng)制要求跛梗,括號在 case 語句里面是不必要的寻馏。但是當(dāng)一個(gè) case 包含了多行語句的時(shí)候,需要加上括號核偿。
switch (condition) {
case 1:
// ...
break;
case 2: {
// ...
// Multi-line example using braces
break;
}
case 3:
// ...
break;
default:
// ...
break;
}
有時(shí)候可以使用 fall-through 在不同的 case 里面執(zhí)行同一段代碼诚欠。一個(gè) fall-through? 是指移除 case 語句的 “break” 然后讓下面的 case 繼續(xù)執(zhí)行。
switch (condition) {
case 1:
case 2:
// code executed for values 1 and 2
break;
default:
// ...
break;
}
常量
相對字符串字面量或數(shù)字,我們更推薦適用常量轰绵。應(yīng)使用static方式聲明常量粉寞,而非使用#define的方式來定義宏。
例如:
恰當(dāng)用法:
static?NSString?*?const?NYTAboutViewControllerCompanyName?=@"The New York Times Company";
static?const?CGFloat NYTImageThumbnailHeight?=50.0;
不當(dāng)用法:
#define CompanyName @"The?New?York Times Company"
#define thumbnailHeight 2
枚舉類型
在使用enum的時(shí)候左腔,推薦適用最新的fixed underlying type(WWDC 2012 session 405- Modern Objective-C)規(guī)范唧垦,因?yàn)樗邆涓鼜?qiáng)的類型檢查和代碼完成功。
例如:
typedefNS_ENUM(NSInteger, NYTAdRequestState) {
NYTAdRequestStateInactive,
NYTAdRequestStateLoading
};
布爾變量
因?yàn)閚il將被解析為NO液样,因此沒有必要在條件語句中進(jìn)行比較振亮。永遠(yuǎn)不要將任何東西和YES進(jìn)行直接比較,因?yàn)閅ES被定義為1鞭莽,而一個(gè)BOOL變量可以有8個(gè)字節(jié)坊秸。
例如:
恰當(dāng)用法:
if(!someObject) {
}
不當(dāng)用法:
if(someObject==nil) {
}
以下是BOOL變量的使用:
恰當(dāng)用法:
if(isAwesome)
if(![someObject boolValue])
不當(dāng)用法:
if([someObject boolValue]==NO)
if(isAwesome==YES)// Never do this.
三目運(yùn)算
僅當(dāng)使用該運(yùn)算子可以讓代碼顯得更清晰易懂時(shí)方可使用三元運(yùn)算子,切三目運(yùn)算體內(nèi)應(yīng)均為運(yùn)算結(jié)果,不然被忽略的錯(cuò)誤比較容易產(chǎn)生撮抓。 更多情況下應(yīng)使用條件語句妇斤。使用類似if的條件語句對多種條件進(jìn)行判斷通常要更容易理解,或使用實(shí)例變量丹拯。
恰當(dāng)用法:
result=a>b?x:y;
不當(dāng)用法:
result=a>b?x=c>d?c:d:y;
CGRect函數(shù)
當(dāng)需要獲取一個(gè)CGRect矩形的x,y,width,height屬性時(shí)站超,應(yīng)使用CGGeometry函數(shù),而非直接訪問結(jié)構(gòu)體成員乖酬。
例如:
恰當(dāng)用法:
CGRect frame=self.view.frame;
CGFloat x=CGRectGetMinX(frame);
CGFloat y=CGRectGetMinY(frame);
CGFloat width=CGRectGetWidth(frame);
CGFloat height=CGRectGetHeight(frame);
不當(dāng)用法:
CGRect frame=self.view.frame;
CGFloat x=frame.origin.x;
CGFloat y=frame.origin.y;
CGFloat width=frame.size.width;
CGFloat height=frame.size.height;
單例
在創(chuàng)建單例對象的共享實(shí)例時(shí)死相,應(yīng)使用線程安全模式,獲取單例對象類方法命名使用sharedXXXX咬像。
例如:
(instancetype)sharedInstance{
staticidsharedInstance?=nil;
staticdispatch_once_tonceToken;
dispatch_once(&onceToken,?^{
sharedInstance?=?[[self alloc] init];
});
return?sharedInstance;
}
美化代碼:
空格
方法的大括號和其他的大括號(if/else/switch/while?等) 總是在同一行開始算撮,在新起一行結(jié)束。
推薦:
if?(user.isHappy) {
//Do something
}
else?{
//Do something else
}
不推薦:
if?(user.isHappy)
{
//Do something
}?else?{
//Do something else
}
換行
self.productsRequest = [[SKProductsRequest?alloc]?initWithProductIdentifiers:productIdentifiers];
一個(gè)像上面的長行的代碼在第二行以一個(gè)間隔(2個(gè)空格)延續(xù)
self.productsRequest = [[SKProductsRequest?alloc]
initWithProductIdentifiers:productIdentifiers];
利用代碼塊
一個(gè) GCC 非常模糊的特性县昂,以及 Clang 也有的特性是肮柜,代碼塊如果在閉合的圓括號內(nèi)的話,會返回最后語句的值
NSURL?*url = ({
NSString?*urlString = [NSString?stringWithFormat:@"%@/%@", baseURLString, endpoint];
[NSURL?URLWithString:urlString];
});
所有的變量都在代碼塊中倒彰,也就是只在代碼塊的區(qū)域中有效审洞,這意味著可以減少對其他作用域的命名污染。
Pragma Mark
#pragma mark -?是一個(gè)在類內(nèi)部組織代碼并且?guī)椭惴纸M方法實(shí)現(xiàn)的好辦法待讳。 我們建議使用?#pragma mark -?來分離:
#pragma mark?- View Lifecycle (View 的生命周期)
- (void)viewDidLoad {?/* ... */?}
- (void)viewWillAppear:(BOOL)animated {?/* ... */?}
- (void)didReceiveMemoryWarning {?/* ... */?}
#pragma mark?- Custom Accessors (自定義訪問器)
- (void)setCustomProperty:(id)value {?/* ... */?}
- (id)customProperty {?/* ... */?}
建立委托者和數(shù)據(jù)源使用“weak關(guān)鍵字”
@property?(nonatomic,?weak)?id delegate;
@property?(nonatomic,?weak)?id dataSource;
默認(rèn)情況下芒澜,委托對象需要實(shí)現(xiàn) protocol 的方法〈吹可以用@required?和?@optional?關(guān)鍵字來標(biāo)記方法是否是必要的還是可選的痴晦。
@protocol?ZOCSignUpViewControllerDelegate?
@required
- (void)signUpViewController:(ZOCSignUpViewController *)controller?didProvideSignUpInfo:(NSDictionary?*);
@optional
- (void)signUpViewControllerDidPressSignUpButton:(ZOCSignUpViewController *)controller;
@end
對于可選的方法,委托者必須在發(fā)送消息前檢查委托是否確實(shí)實(shí)現(xiàn)了特定的方法(否則會 crash):
if?([self.delegate?respondsToSelector:@selector(signUpViewControllerDidPressSignUpButton:)]) {
[self.delegate?signUpViewControllerDidPressSignUpButton:self];
}