1、OC 語言由 smallTalk 演化而來,后者是消息型語言的鼻祖。
2、消息語言與函數(shù)調(diào)用語言的關(guān)鍵區(qū)別在于:使用消息結(jié)構(gòu)的語言,其運行時所應(yīng)執(zhí)行的代碼由運行環(huán)境決定;而使用函數(shù)調(diào)用的語言,則由編譯器決定。
3、OC 的重要工作都是由“運行期組件”而非編譯器來完成。使用 OC 的面向?qū)ο筇匦匀繑?shù)據(jù)結(jié)構(gòu)及函數(shù)都在運行期組件里面。舉例來說,運行期組件中含有全部內(nèi)存管理方法。運行期組件本質(zhì)上就是一種與開發(fā)者所編代碼相連接的“動態(tài)庫”,其代碼能把開發(fā)者編寫的所有程序粘合起來。這樣的話,只需更新運行期組件,即刻提升應(yīng)用程序性能。而那許多工作都在“編譯期”完成的語言,若想獲得類似的性能提升,則要重新編譯應(yīng)用程序代碼。
4、OC 是 C 的“超集”,所以 C 語言中的所有功能在編寫 OC 代碼時依然適用。因此,必須同時掌握 C 與 OC 這兩門語言的核心概念。其中尤為重要的是要理解 C 語言的內(nèi)存模型,這有助于理解 OC 的內(nèi)存模型及其“引用計數(shù)”機(jī)制的工作原理。
5、對象所占內(nèi)存總是分配在“堆空間”中,不能在棧中分配 OC 對象。
NSString *someString = @"hello”;
NSString *anotherString = someString;

如上圖:someString 變量指向分配在堆中的某塊內(nèi)存,其中含有一個NSString對象。再創(chuàng)建一個變量anotherString,令其指向同一地址,并不拷貝對象,只是這兩個變量會同時指向此對象。
在堆上只是一個 NSString 實例,然而有兩個變量指向此實例,兩個變量都是 NSStirng * 型,這說明當(dāng)前“棧針”里分配了兩塊內(nèi)存,這兩塊內(nèi)存里的值都一樣,都是 NSString 實例的內(nèi)存地址
這一點可以解釋為什么OC中不能用“==”來判斷兩個字符串是否相等,答案見http://www.itdecent.cn/p/e4c29a1afbf9
6、分配在堆中的內(nèi)存必須直接管理,而分配在棧上用于保存變量的內(nèi)存則會在其棧針要彈出時自動清理。
7、在 OC 代碼中,有時會遇到不帶 * 的變量,它們可能會使用“??臻g”。這些變量保存的不是 OC 對象。比如 CoreGraphics 框架中的CGRect。
CGRect frame;
frame.origin.x = 0.0f;
frame.origin.y = 10.0f;
frame.size.width = 100.0f;
frame.size.height = 150.0f;
CGRect 是 C 結(jié)構(gòu)體,其定義是:
struct CGRext {
CGPoint origin;
CGSize size;
}
整個系統(tǒng)框架都在使用這種結(jié)構(gòu)體,因為如果改用 OC 對象來做的話,性能會受影響。與創(chuàng)建結(jié)構(gòu)體相比,創(chuàng)建對象還需要額外開銷。
要點
① OC 為 C 語言添加了面向?qū)ο筇匦裕瞧涑?。OC 使用動態(tài)綁定的消息結(jié)構(gòu),也就是說,在運行時才會檢查對象類型。接收一條消息之后,究竟應(yīng)該執(zhí)行何種代碼,由運行期環(huán)境而非編譯器來決定。
② 理解 C 語言的核心概念有助于寫好 OC 程序。尤其要掌握內(nèi)存模型與指針。比如要聲明某個類遵循一項協(xié)議。這種情況下,盡量把“該類遵循某協(xié)議”的這條聲明移至“class-continuation 分類”中。如果不行的話,就把協(xié)議單獨放在一個頭文件中,然后將其引入。