1.了解Objective-C語言的起源
消息結(jié)構(gòu)語言:其運(yùn)行時(shí)所執(zhí)行的代碼由運(yùn)行環(huán)境來決定
函數(shù)調(diào)用語言:編譯器決定
Objective-C 采用消息結(jié)構(gòu)
堆棧區(qū)別
http://blog.csdn.net/a7458969/article/details/6683416
- 深拷貝淺拷貝
- 淺拷貝碴卧,只是對指針的拷貝弱卡,拷貝后兩個(gè)指針指向同一個(gè)內(nèi)存空間
- 深拷貝不但對指針進(jìn)行拷貝,而且對指針指向的內(nèi)容進(jìn)行拷貝住册,經(jīng)深拷貝后的指針是指向兩個(gè)不同地址的指針
2.在類的頭文件中盡量少引入其他頭文件
#include 容易導(dǎo)致死循環(huán)
-
除非確有必要婶博,否則不要使用#import
- 產(chǎn)生相互依賴問題
- 增加編譯時(shí)間
盡量使用@class(forward declaring)
3.多用字面量語法,少用與之等價(jià)的方法
- 字面量語法其實(shí)就是語法糖
- 更簡潔荧飞、易于理解
- 當(dāng)數(shù)組凡人、字典中有nil,會拋出異常
<pre><code>
-(void)example3_syntacticSugarWithNil{
id object1 = @"object1";
id object2 = nil;
id object3 = @1;
NSArray *arrayWithoutSyntacticSugar = [NSArray arrayWithObjects:object1,object2,object3, nil];
pr_obj(arrayWithoutSyntacticSugar);
NSArray *arrayWithSynacticSugar = @[object1,object2,object3];
pr_obj(arrayWithSynacticSugar);
}
</pre></code>
因?yàn)閍rrayWithObjects:方法依次處理各個(gè)參數(shù)叹阔,直到發(fā)現(xiàn)nil為止挠轴,因?yàn)閛bject2是nil,所以方法會提前結(jié)束耳幢,arrayWithoutSyntacticSugar只包含object1
使用字面量語法岸晦,當(dāng)有nil時(shí),會拋出異常,應(yīng)用終止執(zhí)行委煤,便于發(fā)現(xiàn)錯(cuò)誤堂油。
但對于很多app來說,app閃退并不是一件好事碧绞,用戶體驗(yàn)不好府框。為了降低閃退率,而不使用字面量語法讥邻。表面上app的閃退率下降了迫靖,但實(shí)際上,為app埋了隱藏的bug兴使,排查bug難度加大系宜。在我看來,寧愿拋出異常出現(xiàn)閃退发魄,也好過掩蓋錯(cuò)誤盹牧,為app埋下炸彈,某個(gè)時(shí)間突然爆炸励幼,一發(fā)不可收拾汰寓。
-
局限性
- 如果自定義子類,無法用字面量語法創(chuàng)建對象
- 使用字面量語法創(chuàng)建出來的字符串苹粟、數(shù)組有滑、字典對象均為不可變
編譯成功:
運(yùn)行后帚豪,閃退:
4.多用類型常量役听,少用#define預(yù)處理指令
- #define
- 沒有類型信息
- 重新定義常量值,編譯器不會產(chǎn)生警告
<pre><code>#define ANIMATION_DURATION 0.3</pre></code>
- static const
- 描述了常量的含義
- 如果不加static躏救,編譯器默認(rèn)添加extern
- 如果修改const修飾符聲明的變量苛秕,編譯器會報(bào)錯(cuò)
<pre><code>static const NSTimeInterval kAnimationDuration = 0.3;</pre></code>
- extern
- 在頭文件使用extern聲明全局常量肌访,在相關(guān)實(shí)現(xiàn)文件中定義值
<pre><code>extern NSString *const EOCLoginManagerDidLoginNotification;</pre></code>
5.用枚舉表示狀態(tài)、選項(xiàng)艇劫、狀態(tài)碼
- 枚舉默認(rèn)從0開始
TestConnectionState定義:
<pre><code>
typedef enum {
TestConnectionStateDisconnected,
TestConnectionStateConnecting,
TestConnectionStateConnected,
}TestConnectionState;
</pre></code>
打印枚舉值:
<pre><code>
-(void)example4_enumWithDefault{
pr_int(TestConnectionStateDisconnected);
pr_int(TestConnectionStateConnecting);
pr_int(TestConnectionStateConnected);
}
</pre></code>
- 枚舉也可以指定數(shù)值
<pre><code>
typedef enum {
TestConnectionStateStartWithTwoDisconnected = 2,
TestConnectionStateStartWithTwoConnecting = 4,
TestConnectionStateStartWithTwoConnected = 5,
}TestConnectionStateStartWithTwo;
</pre></code>
打印枚舉值:
<pre><code>
-(void)example4_enumStartWithTwo{
pr_int(TestConnectionStateStartWithTwoDisconnected);
pr_int(TestConnectionStateStartWithTwoConnecting);
pr_int(TestConnectionStateStartWithTwoConnected);
}
</pre></code>
- 如果把傳遞給某個(gè)方法的選項(xiàng)表示為枚舉類型场靴,而多個(gè)選項(xiàng)又可同時(shí)使用,那么將各個(gè)選項(xiàng)值定義為2的冪港准,通過按位或操作將其組合起來
以UIViewAutoresizing為例,在UIView.h文件中可以看到UIViewAutoresizing的聲明:
<pre><code>
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
</pre></code>
通過按位與咧欣,可以快速判斷是否包含某個(gè)選項(xiàng):
<pre><code>
-(void)example4_UIViewAutoresizing{
UIViewAutoresizing resizing = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin;
if(resizing & UIViewAutoresizingFlexibleLeftMargin){
pr_obj(@"UIViewAutoresizingFlexibleLeftMargin");
}
if(resizing & UIViewAutoresizingFlexibleHeight){
pr_obj(@"UIViewAutoresizingFlexibleHeight");
}
}
</pre></code>
- 用NS_ENUM與NS_OPTIONS宏來定義枚舉類型浅缸,并指明其底層數(shù)據(jù)類型,而不采用編譯器所選的類型
- (!!!!并沒有任何提示)在處理枚舉類型的switch語句不要實(shí)現(xiàn)default分支魄咕。加入新枚舉后衩椒,編譯器會提示switch語句并未處理所有枚舉
<pre><code>
typedef NS_ENUM(NSInteger,TestSwitchState) {
TestSwitchStateAAA,
TestSwitchStateBBB,
TestSwitchStateCCC,
TestSwitchStateNone,
TestSwitchStateDDD
};
</pre></code>
結(jié)果并沒有任何提示: