Effective Objective-C 2.0讀書筆記(一)

熟悉Objective-C#

第一條:Objective-C的起源

OC使用"消息結構"而非"函數調用",Objective-C語言由Smalltalk演化而來,消息與函數調用之間的區別看上去就像這樣:

//消息結構(Objective-C)
Object *obj = [Object new];
[obj performWith:parameter1 and:parameter1];

//函數調用(C++)
Object *obj = new Object;
obj->perform(parameter1,parameter2);

關鍵區別在于:使用消息結構的語言,其運行時所應執行的代碼由運行環境來決定;而使用函數調用的語言,則由編譯器決定。

要點

  • Objective-C為C語言的添加了面向對象特性,是其超級。Objective—C使用動態綁定的消息結構,也就是說,在運行時才會檢查對象類型。接收一條消息之后,究竟應執行何種代碼,由運行環境而非編譯器來決定。
  • 理解C語言的核心概念有助于寫好Objective-C程序。尤其要掌握內存模型和指針。

第二條:在類的頭文件中盡量少引入其他頭文件

你可能創建了名為EOCPerson和EOCEMPloyer這兩個類,想讓每個EOCPerson實例都有一個EOCEMPloyer常見的辦法是在EOCPerson.h中加入下面這行:

#import "EOCEMPloyer.h"

這種辦法可行,但是不夠優雅。在編譯一個使用了EOCPerson類的文件時,不需要知道EOCEmplyer類的全部細節,只需要知道有一個類名為EOCEmplyer就好。所幸有個辦法能把這一情況告訴編譯器:

@class EOCEmployer;

這叫做"向前聲明"該類。而EOCPerson類的實現文件則需引入EOCEployer類的頭文件,因為若要使用后者,則必須知道其所有接口細節。
將引入頭文件的時機盡量延后,只有確有需要時才引入,這樣就可以減少類的使用者所需引入的頭文件數量。假設本例把EOCEmployer.h引入到EOCPerson.h,那么只要引入EOCPerson.h,就會一并引入EOCEployer.h的所有內容。此過程若持續下去,則要引入許多根本用不到的內容,這當然會增加編輯時間。向前聲明也解決了兩個類互相引用的問題。

如果要聲明你寫的類遵從某個協議(protocol),那么該協議必須有完整定義,且不能使用向前聲明。向前聲明只能告訴編譯器有某個協議,而此時編譯器卻要知道該協議中定義的方法。此時在.h中#import是難免的。鑒于此,最好把協議單獨放在一個頭文件中。要是把協議放在某個大的頭文件中,那么只要引入此協議,就必定會引入那個頭文件中的全部內容,就會產生相互依賴的問題,而且還會增加編譯時間。

然而有些協議,比如代理協議,就不用單獨寫一個頭文件了。在這種情況下協議只有與接受協議委托的類放在一起定義才有意義。

要點

  • 除非確有需要,否則不要引入頭文件。一般來說,應該在某個類的頭文件中使用向前聲明來提及別的類,并在實現文件中引入那些類的頭文件。這樣做可以盡量降低類之間的耦合。
  • 有時無法使用向前聲明,比如聲明某個類遵循某項協議。應盡量把“該類遵循某協議"的這條聲明移至"class-continuation 分類"中。如果不行的話,就把協議放到一個頭文件中,然后將其引入。

第三條:多用字面量語法,少用與之等價的方法

使用字面量語法可以縮減代碼長度,使其更為易讀。例如:

NSNumber *intNumber = @1;
NSArray *animals = @[@"cat",@"dog",@"mouse",@"badger"];
NSDictionary *personData = @{@"firstName":@"Matt",@"lastName":@"Galloway"};

數組取某個下標所對應的對象,例如:

NSString *dog = animals[1];

字典按照特定鍵訪問其值,例如:

NSString *lastName = personData[@"lastName"];

修改可變數組與字典內容的標準做法是:

mutableArray[1] = @"dog";
mutableDictionary[@"lastName"] = @"Galloway";

不過,用字面量語法創建數組時要注意,若數組元素對象中有nil,則會拋出異常,拋出的異常會是這樣:

***Terminating app due to uncaught exception
'NSInvalidArgumentException,'reason:'***
- [__NSPlaceholderArray initWithObjects:count:]: attempt to
insert nil object from objects[0]'

用數組一樣,用字面量語法創建字典時也有這個問題,那就是一旦有值為nil,便會拋出異常。但這也是個好事。例如創建字典時不小心用了空值對象,那么“dictionaryWithObjectAndKeys:”方法就會在首個nil之前停下,并拋出異常,這樣有助于差錯。

要點

  • 應該使用字面量語法來創建字符串,數值,數組,字典。與常規方法相比,這樣做更加簡明扼要。
  • 應該通過去下標操作來訪問數組下標或字典中的鍵所對應的元素。
  • 用字面量語法創建數組或字典時,若值中有nil,則會拋出異常。因此,務必確保值里不含nil。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容