熟悉Objective-C#
第一條:Objective-C的起源
OC使用"消息結(jié)構(gòu)"而非"函數(shù)調(diào)用",Objective-C語言由Smalltalk演化而來,消息與函數(shù)調(diào)用之間的區(qū)別看上去就像這樣:
//消息結(jié)構(gòu)(Objective-C)
Object *obj = [Object new];
[obj performWith:parameter1 and:parameter1];
//函數(shù)調(diào)用(C++)
Object *obj = new Object;
obj->perform(parameter1,parameter2);
關(guān)鍵區(qū)別在于:使用消息結(jié)構(gòu)的語言,其運行時所應(yīng)執(zhí)行的代碼由運行環(huán)境來決定辞槐;而使用函數(shù)調(diào)用的語言,則由編譯器決定榄檬。
要點
- Objective-C為C語言的添加了面向?qū)ο筇匦裕瞧涑壉拧bjective—C使用動態(tài)綁定的消息結(jié)構(gòu),也就是說犬缨,在運行時才會檢查對象類型。接收一條消息之后刺彩,究竟應(yīng)執(zhí)行何種代碼,由運行環(huán)境而非編譯器來決定创倔。
- 理解C語言的核心概念有助于寫好Objective-C程序。尤其要掌握內(nèi)存模型和指針畦攘。
第二條:在類的頭文件中盡量少引入其他頭文件
你可能創(chuàng)建了名為EOCPerson和EOCEMPloyer這兩個類,想讓每個EOCPerson實例都有一個EOCEMPloyer常見的辦法是在EOCPerson.h中加入下面這行:
#import "EOCEMPloyer.h"
這種辦法可行,但是不夠優(yōu)雅知押。在編譯一個使用了EOCPerson類的文件時鹃骂,不需要知道EOCEmplyer類的全部細節(jié)台盯,只需要知道有一個類名為EOCEmplyer就好畏线。所幸有個辦法能把這一情況告訴編譯器:
@class EOCEmployer;
這叫做"向前聲明"該類。而EOCPerson類的實現(xiàn)文件則需引入EOCEployer類的頭文件寝殴,因為若要使用后者明垢,則必須知道其所有接口細節(jié)。
將引入頭文件的時機盡量延后袖外,只有確有需要時才引入魂务,這樣就可以減少類的使用者所需引入的頭文件數(shù)量曼验。假設(shè)本例把EOCEmployer.h引入到EOCPerson.h,那么只要引入EOCPerson.h粘姜,就會一并引入EOCEployer.h的所有內(nèi)容。此過程若持續(xù)下去孤紧,則要引入許多根本用不到的內(nèi)容,這當然會增加編輯時間号显。向前聲明也解決了兩個類互相引用的問題。
如果要聲明你寫的類遵從某個協(xié)議(protocol),那么該協(xié)議必須有完整定義押蚤,且不能使用向前聲明。向前聲明只能告訴編譯器有某個協(xié)議揽碘,而此時編譯器卻要知道該協(xié)議中定義的方法。此時在.h中#import是難免的雳刺。鑒于此,最好把協(xié)議單獨放在一個頭文件中掖桦。要是把協(xié)議放在某個大的頭文件中,那么只要引入此協(xié)議枪汪,就必定會引入那個頭文件中的全部內(nèi)容,就會產(chǎn)生相互依賴的問題,而且還會增加編譯時間朱监。
然而有些協(xié)議,比如代理協(xié)議赫编,就不用單獨寫一個頭文件了奋隶。在這種情況下協(xié)議只有與接受協(xié)議委托的類放在一起定義才有意義。
要點
- 除非確有需要唯欣,否則不要引入頭文件。一般來說境氢,應(yīng)該在某個類的頭文件中使用向前聲明來提及別的類碰纬,并在實現(xiàn)文件中引入那些類的頭文件萍聊。這樣做可以盡量降低類之間的耦合悦析。
- 有時無法使用向前聲明,比如聲明某個類遵循某項協(xié)議强戴。應(yīng)盡量把“該類遵循某協(xié)議"的這條聲明移至"class-continuation 分類"中。如果不行的話骑歹,就把協(xié)議放到一個頭文件中,然后將其引入陵刹。
第三條:多用字面量語法,少用與之等價的方法
使用字面量語法可以縮減代碼長度衰琐,使其更為易讀。例如:
NSNumber *intNumber = @1;
NSArray *animals = @[@"cat",@"dog",@"mouse",@"badger"];
NSDictionary *personData = @{@"firstName":@"Matt",@"lastName":@"Galloway"};
數(shù)組取某個下標所對應(yīng)的對象狸剃,例如:
NSString *dog = animals[1];
字典按照特定鍵訪問其值,例如:
NSString *lastName = personData[@"lastName"];
修改可變數(shù)組與字典內(nèi)容的標準做法是:
mutableArray[1] = @"dog";
mutableDictionary[@"lastName"] = @"Galloway";
不過钞馁,用字面量語法創(chuàng)建數(shù)組時要注意,若數(shù)組元素對象中有nil僧凰,則會拋出異常熟丸,拋出的異常會是這樣:
***Terminating app due to uncaught exception
'NSInvalidArgumentException,'reason:'***
- [__NSPlaceholderArray initWithObjects:count:]: attempt to
insert nil object from objects[0]'
用數(shù)組一樣训措,用字面量語法創(chuàng)建字典時也有這個問題,那就是一旦有值為nil绩鸣,便會拋出異常。但這也是個好事呀闻。例如創(chuàng)建字典時不小心用了空值對象,那么“dictionaryWithObjectAndKeys:”方法就會在首個nil之前停下蓖康,并拋出異常,這樣有助于差錯钓瞭。
要點
- 應(yīng)該使用字面量語法來創(chuàng)建字符串,數(shù)值山涡,數(shù)組,字典鸭丛。與常規(guī)方法相比,這樣做更加簡明扼要鳞溉。
- 應(yīng)該通過去下標操作來訪問數(shù)組下標或字典中的鍵所對應(yīng)的元素鼠哥。
- 用字面量語法創(chuàng)建數(shù)組或字典時熟菲,若值中有nil朴恳,則會拋出異常。因此于颖,務(wù)必確保值里不含nil。