編寫Objective-C程序時,總會用到某幾個類,它們屬於Foundation框架。雖然從技術上來說,不用Foundation框架也能寫出Objective-C代碼,但實際上卻經常要用到此框架。這幾個類是NSString、NSNumber、NSArray、NSDictionary。從類名上即可看出各自所表示的數據結構。
Objective-C以語法繁雜而著稱。事實上的確是這樣。不過,從Objective-C 1.0起,有一種非常簡單的方式能創建NSString對象。這就是“字符串字面量”(string literal),其語法如下:
NSString *someString = @”Effective Objective-C 2.0”;
如果不用這種語法的話,就要以常見的alloc及init方法來分配並初始化NSString對象了。在版本較新的編譯器中,也能用這種字面量語法來聲明NSNumber、NSArray、NSDictionary類的實例。使用字面量語法(literal syntax)可以縮減源代碼長度,使其更為易讀。
字面數值
有時需要把整數、浮點數、布爾值封入Objective-C對象中。這種情況下可以用NSNumber類,該類可處理多種類型的數值。若是不用字面量,那麼就需要按下述方式創建實例:
NSNumber *someNumber = [NSNumber numberWithInt:1];
上面這行代碼創建了一個數字,將其值設為整數1。然而使用字面量能令代碼更為整潔:
NSNumber *someNumber = @1;
大家可以看到,字面量語法更為精簡。不過它還有很多好處。能夠以NSNumber實例表示的所有數據類型都可使用該語法。例如:
NSNumber intNumber = @1;
NSNumber floatNumber = @2.5f;
NSNumber doubleNumber = @3.14159;
NSNumber boolNumber = @YES;
NSNumber *charNumber = @’a’;
字面量語法也適用於下述表達式:
以字面量來表示數值十分有用。這樣做可以令NSNumber對象變得整潔,因為聲明中只包含數值,而沒有多余的語法成分。
字面量數組
數組是常用的數據結構。如果不使用字面量語法,那麼就要這樣來創建數組:
而使用字面量語法來創建則是:
上面這種做法不僅簡單,而且還利於操作數組。數組的常見操作就是取某個下標所對應的對象,這用字面量來做更為容易。如果不用字面量,那麼通常會用“objectAtIndex:”方法:
若使用字面量,則是:
這也叫做“取下標”操作(subscripting),與使用字面量語法的其他情況一樣,這種方式也更為簡潔、更易理解,而且與其他語言中依下標來訪問數組元素時所用的語法類似。
不過,用字面量語法創建數組時要注意,若數組元素對象中有nil,則會拋出異常,因為字面量語法實際上只是一種“語法糖”(syntactic sugar),其效果等於是先創建了一個數組,然後把方括號內的所有對象都加到這個數組中。拋出的異常會是這樣:
*** Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '***
-[__NSPlaceholderArray initWithObjects:count:]: attempt to
insert nil object from objects[0]'
在改用字面量語法來創建數組時就會遇到這個問題。下面這段代碼分別以兩種語法創建數組:
id object1 = /* ... */;
id object2 = /* ... */;
id object3 = /* ... */;
NSArray *arrayA = [NSArray array WithObjects:
object1, object2, object3, nil];
NSArray *arrayB = @[object1, object2, object3];
大家想想:如果object1與object3都指向了有效的Objective-C對象,而object2是nil,那麼會出現什麼情況呢?按字面量語法創建數組arrayB時會拋出異常。arrayA雖然能創建出來,但是其中卻只含有object1一個對象。原因在於,“arrayWithObjects:”方法會依次處理各個參數,直到發現nil為止,由於object2是nil,所以該方法會提前結束。
這個微妙的差別表明,使用字面量語法更為安全。拋出異常令應用程序終止執行,這比創建好數組之後才發現元素個數少了要好。向數組中插入nil通常說明程序有錯,而通過異常可以更快地發現這個錯誤。
字面量字典
“字典”(Dictionary)是一種映射型數據結構,可向其中添加鍵值對。與數組一樣,Objective-C代碼也經常用到字典。其創建方式如下:
這樣寫令人困惑,因為其順序是,,,。這與通常理解的順序相反,我們一般認為是把“鍵”映射到“對象”。因此,這種寫法不容易讀懂。如果改用字面量語法,就清晰多了:
上面這種寫法更簡明,而且鍵出現在對象之前,理解起來較順暢。此范例代碼還說明了使用字面量數值的好處。字典中的對象和鍵必須都是Objective-C對象,所以不能把整數28直接放進去,而要將其封裝在NSNumber實例中才行。使用字面量語法很容易就能做到這一點,只需給數字前加一個@字符即可。
與數組一樣,用字面量語法創建字典時也有個問題,那就是一旦有值為nil,便會拋出異常。不過基於同樣的原因,這也是個好事。假如在創建字典時不小心用了空值對象,那麼“dictionaryWithObjectsAndKeys:”方法就會在首個nil之前停下,並拋出異常,這有助於查錯。
字典也可以像數組那樣用字面量語法訪問。按照特定鍵訪問其值的傳統做法是:
與之等效的字面量語法則是:
這樣寫也省去了冗贅的語法,令此行代碼簡單易讀。
可變數組與字典
通過取下標操作,可以訪問數組中某個下標或字典中某個鍵所對應的元素。如果數組與字典對象是可變的(mutable),那麼也能通過下標修改其中的元素值。修改可變數組與字典內容的標准做法是:
若換用取下標操作來寫,則是:
局限性
字面量語法有個小小的限制,就是除了字符串以外,所創建出來的對象必須屬於Foundation框架才行。如果自定義了這些類的子類,則無法用字面量語法創建其對象。要想創建自定義子類的實例,必須采用“非字面量語法”(nonliteral syntax)。然而,由於NSArray、NSDictionary、NSNumber都是業已定型的“子族”(class cluster,參見第9條),因此很少有人會從其中自定義子類,真要那樣做也比較麻煩。而且一般來說,標准的實現已經很好了,無須再改動。創建字符串時可以使用自定義的子類,然而必須要修改編譯器的選項才行。除非你明白這樣做的後果,否則不鼓勵使用此選項,用NSString就足夠了。
使用字面量語法創建出來的字符串、數組、字典對象都是不可變的(immutable)。若想要可變版本的對象,則需復制一份:
這麼做會多調用一個方法,而且還要再創建一個對象,不過使用字面量語法所帶來的好處還是多於上述缺點的。
要點
應該使用字面量語法來創建字符串、數值、數組、字典。與創建此類對象的常規方法相比,這麼做更加簡明扼要。
應該通過取下標操作來訪問數組下標或字典中的鍵所對應的元素。
用字面量語法創建數組或字典時,若值中有nil,則會拋出異常。因此,務必確保值裡不含nil。
Objective-C中@property的所有屬性詳解 http://www.linuxidc.com/Linux/2014-03/97744.htm
Objective-C 和 Core Foundation 對象相互轉換的內存管理總結 http://www.linuxidc.com/Linux/2014-03/97626.htm
使用 Objective-C 一年後我對它的看法 http://www.linuxidc.com/Linux/2013-12/94309.htm
10個Objective-C基礎面試題,iOS面試必備 http://www.linuxidc.com/Linux/2013-07/87393.htm
Objective-C適用C數學函數 <math.h> http://www.linuxidc.com/Linux/2013-06/86215.htm
好學的 Objective-C 高清PDF http://www.linuxidc.com/Linux/2014-09/106226.htm