iOS9 with Swift 集合類(lèi)型(一)

集合類(lèi)型:

Swift,和其他現(xiàn)代編程語(yǔ)言一樣,有內(nèi)置的集合類(lèi)型數(shù)組(Array)和字典(Dictionary),還增加了第三種類(lèi)型集合(Set)。數(shù)組和字典非常重要以至于Swift提供了很多特殊的語(yǔ)法。同時(shí)像其他的大部分Swift類(lèi)型,它也提供了一些相關(guān)的的函數(shù);NSArray和NSDictionary也會(huì)補(bǔ)充一些丟失的函數(shù)。而集合類(lèi)型則是橋接至Cocoa的NSSet。

數(shù)組(Array):

數(shù)組(結(jié)構(gòu)體)是有序的對(duì)象實(shí)例的集合(數(shù)組的元素),可以使用Int類(lèi)型的序號(hào)來(lái)取出元素。而且序號(hào)是從0開(kāi)始的。比如一個(gè)數(shù)組有四個(gè)元素,那么它就是從0到3。Swift的數(shù)組是非空的,所以如果有Index3那么就要有0—2.

最顯著的Swift數(shù)組特性是其嚴(yán)格類(lèi)型檢驗(yàn)。不想有些其他的語(yǔ)言,Swift數(shù)組的元素必須統(tǒng)一,也就是說(shuō),其必須是由確定的一種類(lèi)型的元素所組成的。即便是空數(shù)組也必須要有確定的類(lèi)型。元素類(lèi)型不同的兩個(gè)數(shù)組被認(rèn)為是兩種不同的類(lèi)型,數(shù)組類(lèi)型依照元素類(lèi)型遵循多態(tài):如果NoisyDog是Dog的子類(lèi),那么元素是NoisyDog的數(shù)組就可以用在Dog元素?cái)?shù)組的地方。哈哈,沒(méi)錯(cuò)這個(gè)和可選值一樣也是泛型聲明,即Array<Element>,Element就是元素的類(lèi)型。

事實(shí)上數(shù)組類(lèi)型同一限制,可能沒(méi)有你想象的那么宴客。數(shù)組的元素必須是一種類(lèi)型,但是類(lèi)型卻是十分領(lǐng)會(huì)的。通過(guò)選擇合適的數(shù)組類(lèi)型你可以制作出實(shí)際上內(nèi)部有多種類(lèi)型的數(shù)組,比如:

1、如果NoisyDog是Dog的子類(lèi),那么Dog的數(shù)組就可以包含NoisyDog的元素。

2、如果Bird和Insect都采用了Flier協(xié)議,F(xiàn)lier為元素的數(shù)組就可以包含Bird或者Insect。

3、AnyObject元素?cái)?shù)組就可以包含任何Swift的類(lèi)的實(shí)例和橋接類(lèi)的實(shí)例,比如Int,String、Dog。

4、一種類(lèi)型可能承載多個(gè)類(lèi)型,比如枚舉類(lèi)型就可以在關(guān)聯(lián)值中有Int、String等等類(lèi)型。

聲明數(shù)組的類(lèi)型既可以用泛型聲明:Array<Int>,也可以用語(yǔ)法糖聲明:[Int]。后者你會(huì)經(jīng)常使用到。

字面數(shù)組可以使用包含在方括號(hào)中的一系列被逗號(hào)分隔的元素來(lái)表示,空數(shù)組的字面表示形式就是:[]。

數(shù)組的默認(rèn)構(gòu)造器init(),你可以在后面加一對(duì)空的圓括號(hào)來(lái)表示空數(shù)組:

1

如果引用量類(lèi)型可以提前知道,那么該空數(shù)組可以推遲其類(lèi)型,因此你也可以這樣來(lái)創(chuàng)建空數(shù)組:


2

如果你用非空的字面元素來(lái)開(kāi)始,那么你就不需要聲明數(shù)組的類(lèi)型,因?yàn)镾wift會(huì)通過(guò)元素類(lèi)型來(lái)推測(cè)出數(shù)組的類(lèi)型。比如Swift會(huì)推測(cè)[1,2,3]為Int數(shù)組。如果數(shù)組包括父類(lèi)和子類(lèi),那么Swift將會(huì)推測(cè)其為父類(lèi)類(lèi)型數(shù)組。甚至[1, "howdy"]這樣的數(shù)組也是可以的,不過(guò)其類(lèi)型是NSObject。然而在某些情況下,即使你用字面量來(lái)聲明,你最好也現(xiàn)將引用量的類(lèi)型顯式聲明:


3

數(shù)組也有參數(shù)是序列的構(gòu)造器,這就說(shuō)明如果是序列類(lèi)型,你就可以將它分開(kāi)來(lái)充當(dāng)數(shù)組的元素。比如:

1、Array(1...3)就能產(chǎn)生Int類(lèi)型的數(shù)組[1,2,3]。

2、Array("hey".character)就會(huì)產(chǎn)生["h", "e","y"]。

3、Array(d) 其中d是字典,就會(huì)產(chǎn)生key-value對(duì)的元組類(lèi)型數(shù)組。

還有一種構(gòu)造器 init(count:repeatValue:),可以用來(lái)初始化重復(fù)值。比如我要初始化一百個(gè)nil值在String?數(shù)組中。

let strings : [String?] = Array(count:100, repeatedValue: nil)

這是你在Swift中能得到的最接近于缺失數(shù)組的方法:你有100個(gè)空位可以放對(duì)象。

數(shù)組轉(zhuǎn)型和類(lèi)型檢查:

當(dāng)你將一個(gè)數(shù)組分配、傳遞以及轉(zhuǎn)型到另一個(gè)數(shù)組的時(shí)候,你是在每個(gè)元素的層面上去操作的:


4

這段代碼事實(shí)上是簡(jiǎn)寫(xiě):將Int類(lèi)型的數(shù)組賦給Int?類(lèi)型數(shù)組,實(shí)際上是,每一個(gè)原數(shù)組中的元素都要進(jìn)行封包。事實(shí)上是這樣的情況:


5

類(lèi)似地,假如NoisyDog是Dog的子類(lèi),下面的代碼是合法的:


6

在第三行,我們建立了一個(gè)Dog數(shù)組。第四行我們將Dog數(shù)組轉(zhuǎn)型為NoisyDog數(shù)組,這就意味著我們將每個(gè)元素分別轉(zhuǎn)為NoisyDog類(lèi)。

你可以用is運(yùn)算符測(cè)試元素類(lèi)型來(lái)測(cè)試數(shù)組的類(lèi)型:


7

如果每個(gè)元素均為NoisyDog,那么結(jié)果就是True。

同樣的,as?運(yùn)算符將把一個(gè)數(shù)組轉(zhuǎn)為包在可選值中的數(shù)組,如果無(wú)法下行轉(zhuǎn)換,結(jié)果將是nil。


8

數(shù)組轉(zhuǎn)型的目的和其他類(lèi)型的轉(zhuǎn)型是類(lèi)似的——你可以發(fā)送合適的消息給轉(zhuǎn)型后的數(shù)組。如果NoisyDog聲明了Dog類(lèi)沒(méi)有的方法,你就不能向Dog類(lèi)型的數(shù)組發(fā)送該方法。這樣你就需要將元素轉(zhuǎn)型為NoisyDog,然后編譯器才會(huì)讓你去進(jìn)行發(fā)送方法消息。你既可以將其中的元素進(jìn)行轉(zhuǎn)型,也可以將整個(gè)數(shù)組進(jìn)行轉(zhuǎn)型。

數(shù)組的比較:

如果兩個(gè)數(shù)組元素?cái)?shù)一樣且全部相等的話(huà),那么就是相等的。


9


10

數(shù)組是值類(lèi)型:

由于數(shù)組是結(jié)構(gòu)體,所以其不是引用類(lèi)型,而是值類(lèi)型。這就意味著,每一次數(shù)組被分配到變量或者作為函數(shù)參數(shù),它都會(huì)被復(fù)制一份。然而我不是在暗示這種復(fù)制的代價(jià)很大。如果數(shù)組的引用是一個(gè)常量,那么顯然復(fù)制就不是必要的了,甚至從其他數(shù)組產(chǎn)生新數(shù)組的操作或者轉(zhuǎn)變數(shù)組的操作已經(jīng)是非常高效的了。

你只需相信Swift的設(shè)計(jì)者已經(jīng)考慮過(guò)這個(gè)問(wèn)題,而且在后臺(tái)處理數(shù)組是十分高效的。

雖然數(shù)組本身是值類(lèi)型,但是其元素是引用類(lèi)型的還是按照引用類(lèi)型來(lái)對(duì)待。特別是類(lèi)的實(shí)例為元素的數(shù)組,如果被多個(gè)變量引用。那么就會(huì)產(chǎn)生多個(gè)引用這一個(gè)相同的實(shí)例。

數(shù)組下標(biāo):

數(shù)組結(jié)構(gòu)體利用下標(biāo)方法允許通過(guò)在引用變量后面添加包含值的方括號(hào)來(lái)取出元素。值可以是Int比如arr[1] 就是取出arr數(shù)組的第二個(gè)值。值還可以是Int的范圍,比如,arr[1...2]就是去取出第二個(gè)和第三個(gè)值,嚴(yán)格的說(shuō),這會(huì)產(chǎn)生叫做ArraySlice的東西,其非常類(lèi)似于Array,比如你可以用和數(shù)組一樣的下標(biāo)來(lái)取出ArraySlice的元素;而且它也可以用在數(shù)組能用的地方。一般地,你就把他當(dāng)做是數(shù)組就可以了。

如果數(shù)組的引用是可變的(即var,而不是let),那么下標(biāo)的表達(dá)方法也可以用來(lái)被分配值。這會(huì)改變那個(gè)被下標(biāo)表達(dá)元素的值,被分配的值必須是與數(shù)組元素的類(lèi)型一致。


11

如果下標(biāo)是一段區(qū)間,那么賦的值就必須是一個(gè)數(shù)組,這有可能改變數(shù)組的長(zhǎng)度:


12

下標(biāo)超過(guò)應(yīng)有的范圍就會(huì)引起運(yùn)行錯(cuò)誤。

嵌套數(shù)組:

數(shù)組的元素是數(shù)組是合法的。比如:


13

它是Int類(lèi)型數(shù)組的數(shù)組。它的類(lèi)型聲明是[[Int]]。(沒(méi)有規(guī)定說(shuō),內(nèi)部的數(shù)組必須是相同長(zhǎng)度,上面只是為可了便于表達(dá))

為了得到內(nèi)部的數(shù)組元素,你可以使用下標(biāo)鏈:


14

如果外部數(shù)組的引用是可變的,你還可以進(jìn)行寫(xiě)入:


15

你可以用其他方法改編內(nèi)部數(shù)組,比如你可以為它添加新的元素。

基本數(shù)組屬性和方法:

數(shù)組是一個(gè)集合(采用CollectionType協(xié)議),而集合又是一個(gè)序列(采用SequenceType協(xié)議)。如果這些項(xiàng)有熟悉的情景,如同String的characters。從這個(gè)方面來(lái)看,它與字符序列是很像的。

作為集合,數(shù)組的count只讀屬性表示元素的個(gè)數(shù)。當(dāng)count為0時(shí)候,isEmpty屬性就是true。

數(shù)組的first和last只讀屬性返回了它的第一個(gè)和最后一個(gè)元素,但是它們均被可選值包裹,因?yàn)閿?shù)組有可能為空,此時(shí)它們的值就是nil。這是在Swift中比較少見(jiàn)的雙重可選的情況,比如,當(dāng)你聲明一個(gè)類(lèi)型為Int?的數(shù)組的時(shí)候,此時(shí)如果為nil,那么就是Int??。

數(shù)組的最大下標(biāo)比count要少1,有時(shí)你需要引用count來(lái)計(jì)算得出下標(biāo)是多少。比如你可以這樣來(lái)得到數(shù)組的后兩位,

16

Swift不允許你使用負(fù)數(shù)作為這種計(jì)算的捷徑,而另一方面,如果你想要得出倒數(shù)幾位元素,不妨使用suffix方法:


17

對(duì)于suffix和prefix方法,都允許范圍超出:


18

通過(guò)前綴的個(gè)數(shù)多少來(lái)取出元素,還可以用前綴的序數(shù)來(lái)表示取出元素:


19

數(shù)組的starIndex屬性是0,endIndex屬性則是count的值。此外,indices屬性是以starIndex和endIndex為端點(diǎn)的半開(kāi)區(qū)間。也就是可以取出全部元素的范圍。如果你的數(shù)組的引用是可變的,你可以改變startIndex和endIndex來(lái)獲得新的區(qū)間。

20

indexOf方法會(huì)返回某個(gè)元素第一次出現(xiàn)的下標(biāo),要注意此值是可選值。如果該數(shù)組的元素是可比較相等的,那么就可以用==來(lái)識(shí)別是不是要找的元素。


21

即使數(shù)組不是可比較相等的元素,你也是可以用自己的函數(shù)(用元素為參數(shù),返回bool值)來(lái)比較。

22

作為序列,數(shù)組還有contains方法來(lái)驗(yàn)證它是否包含某個(gè)元素,同樣如果元素是可等的,你也可以用==運(yùn)算符,或者你可以提供自己的函數(shù)(參數(shù)為元素類(lèi)型,返回值為Bool)。


23

starWith方法則可以用來(lái)檢驗(yàn)一個(gè)數(shù)組的開(kāi)始元素是不是與給定的序列符合,或者你也可以用==運(yùn)算符,或者你可以提供自己的函數(shù)(參數(shù)為元素類(lèi)型,返回值為Bool):


24

elementsEqual方法則從序列的一般原則比較數(shù)組是否相同:兩個(gè)序列必須等長(zhǎng),而且每個(gè)元素相等。你也可以用==運(yùn)算符,或者你可以提供自己的函數(shù)(參數(shù)為元素類(lèi)型,返回值為Bool)。


25

minElement和maxElement返回最小或者最大的元素,同樣會(huì)被包在可選值中以防為空數(shù)組。如果元素可比,你也可以用<運(yùn)算符,或者你可以提供自己的函數(shù)(參數(shù)為元素類(lèi)型,返回值為Bool)。第三行是驗(yàn)證是否絕對(duì)值較小的數(shù)是兩個(gè)中的前者。


26

如果數(shù)組的引用是可變的,append和appendContentsOf這兩個(gè)實(shí)例方法都可以在數(shù)組末尾添加新元素。兩者的差別是,append參數(shù)只是元素類(lèi)型的單個(gè)值,而appendContentsOf則需要一個(gè)序列作為參數(shù)。比如:


27

+運(yùn)算符被重載為類(lèi)似于appendContentsOf(不是append)。當(dāng)+前的運(yùn)算元是數(shù)組時(shí),它不會(huì)產(chǎn)生新的數(shù)組,所以即使引用的數(shù)組是常量也可以用。如果引用是變量,就可以用+=來(lái)代替:


28

如果數(shù)組的引用量是可變的,實(shí)例方法insert(atIndex:)將單個(gè)元素插入到所給的下標(biāo)處。如果要一次插入多個(gè)元素,可以使用insertContentsOf(at:)方法。

如果數(shù)組的引用量是可變的,實(shí)例方法removeAtIndex可以將該下標(biāo)的元素移除,實(shí)例方法removeLast則會(huì)移除最后一個(gè)元素,removeFirst則會(huì)移除第一個(gè)元素。這些方法也會(huì)將移除的元素返回,如果你不需要返回值,就不用理他們了。這些值不會(huì)被包在可選值里面,并且如果越界會(huì)引起崩潰。removeLast還可以引入Int參數(shù),來(lái)移除多個(gè)值,但是不會(huì)返回值,而且如果越界會(huì)引起崩潰。

另一方面,popFirst和poplast將會(huì)返回可選值,所以即使是空數(shù)組也是安全的。如果引用量是不可變的,你可以用dropFirst和dropLast來(lái)返回改變了的數(shù)組(確切的說(shuō)是ArraySlice)。

實(shí)例方法joinWithSeparator以嵌套數(shù)組開(kāi)頭,它會(huì)取出單獨(dú)的數(shù)組元素,然后將參數(shù)數(shù)組插入到原數(shù)組元素之間。最后的結(jié)果就是被分割的數(shù)組,即JoinSeparater,最后在強(qiáng)制轉(zhuǎn)換成數(shù)組:


29

調(diào)用JoinWithSeparater,以空數(shù)組為參數(shù)可以“夷平”數(shù)組:


30

還有專(zhuān)門(mén)的實(shí)例方法flatten,它會(huì)返回JoinSeparater,然后在強(qiáng)制轉(zhuǎn)換為數(shù)組。

reverse實(shí)例方法會(huì)產(chǎn)生新的數(shù)組,其元素是倒過(guò)來(lái)的。

sortInplace和sort分別能將原始數(shù)組整理順序,和產(chǎn)生新的數(shù)組。同樣你有兩個(gè)選擇,若果是可比較的就可以用<運(yùn)算符,或者提供一個(gè)函數(shù)接受兩個(gè)參數(shù)并返回一個(gè)bool值,

31

在最后一行,我提供了一個(gè)匿名函數(shù),或者你可以傳遞一個(gè)已經(jīng)聲明了的函數(shù)。在Swift中,比較運(yùn)算符就是它的函數(shù)名,因此我可以更簡(jiǎn)潔地這樣做:


32

split實(shí)例方法將數(shù)字分成嵌套數(shù)組,并可以傳遞測(cè)試,通過(guò)測(cè)試的將會(huì)被刪除。

33

數(shù)組枚舉和變形:

數(shù)組是序列,所以你可以將它枚舉化,通過(guò)按順序檢查和操作每個(gè)元素。最簡(jiǎn)單的就是for in循環(huán)


34

或者還可以使用forEach實(shí)例方法,它的參數(shù)是一個(gè)函數(shù),該函數(shù)的參數(shù)是數(shù)組的一個(gè)元素,沒(méi)有返回值。它其實(shí)就是與for in功能類(lèi)似的函數(shù)。


35

如果你還需要元素的下標(biāo),調(diào)用enumerate實(shí)例方法并在結(jié)果處循環(huán),這樣每次循環(huán)得到的都是一個(gè)元組。


36

Swift還提供了,三個(gè)有效的數(shù)組變形實(shí)例方法。比如forEach,這些方法都會(huì)為你枚舉化數(shù)組,所以循環(huán)是隱含在方法調(diào)用中的,這會(huì)使你的代碼更加簡(jiǎn)潔。

我們先從map實(shí)例方法開(kāi)始,它會(huì)產(chǎn)生新數(shù)組,其中的新元素都是原數(shù)組的元素經(jīng)過(guò)我們所提供函數(shù)處理的結(jié)果。該函數(shù)的參數(shù)是數(shù)組元素的類(lèi)型,然后返回的值是有可能為其他類(lèi)型的值。Swift會(huì)自動(dòng)推斷返回的數(shù)組元素的類(lèi)型。

比如:可以為數(shù)組的每個(gè)元素都乘以2


37

下面這個(gè)例子是說(shuō)map可以產(chǎn)生不同類(lèi)型的數(shù)組:


38

實(shí)際開(kāi)發(fā)中的例子:想要將UITableView中的一個(gè)section的cell放到同一個(gè)NSObject數(shù)組中去,sec是section的序號(hào):


39

或者可以用更簡(jiǎn)潔的map方法:


40

由于map實(shí)際上是CollectionType的實(shí)例方法,而區(qū)間(本身就是CollectionType),所以可以進(jìn)一步簡(jiǎn)寫(xiě):


41

filter實(shí)例方法也會(huì)產(chǎn)生一個(gè)新數(shù)組,然而其中的元素是經(jīng)過(guò)過(guò)濾的原數(shù)組元素,你可以提供具體的過(guò)濾函數(shù),該函數(shù)接受一個(gè)元素類(lèi)型值并返回一個(gè)bool值來(lái)驗(yàn)證是否要把該元素過(guò)濾掉。


42

最后就是reduce實(shí)例方法,如果你接觸過(guò)LISP或者Scheme,你可能對(duì)其很熟悉,否則你可能會(huì)覺(jué)得有點(diǎn)晦澀。這是一種將序列中所有元素都結(jié)合在一起的方法,它會(huì)產(chǎn)生唯一的值,該值不一定要與原數(shù)組元素的類(lèi)型一樣。你需要提供的函數(shù)的值有兩個(gè)參數(shù),第一個(gè)參數(shù)是結(jié)果類(lèi)型的值,第二個(gè)參數(shù)是原數(shù)組元素的類(lèi)型的值。每次迭代的結(jié)果會(huì)自動(dòng)成為下一次的第一個(gè)參數(shù),第二個(gè)參數(shù)則為下一個(gè)數(shù)組元素。不過(guò)你需要提供第一次迭代時(shí)的第一個(gè)參數(shù)。最后結(jié)果就是該值和原數(shù)組元素的積累,并且其類(lèi)型為該值的類(lèi)型。

每一個(gè)參數(shù)對(duì)都會(huì)被加總在一起,然后作為下一次迭代的第一個(gè)參數(shù),如果我們要的是全部數(shù)組元素的加總,那么顯然這個(gè)值應(yīng)該是0。


43

再一次,我們可以精簡(jiǎn)這段代碼,因?yàn)?就是需要函數(shù)的名字:


44

在實(shí)際編程中,我相當(dāng)以來(lái)這幾個(gè)方法,經(jīng)常用兩個(gè)以上,將他們嵌套或者鏈起來(lái)。這里有個(gè)例子,雖然看起來(lái)有點(diǎn)復(fù)雜,但是卻很好地解釋了如何使用Swift數(shù)組。


45

Swift Array&Oc NSArray:

當(dāng)你在進(jìn)行iOS編程的時(shí)候,你會(huì)將Foundation框架import(或者可以導(dǎo)入U(xiǎn)IKit,此框架是已經(jīng)導(dǎo)入Foundation的),這樣Oc的NSArray也會(huì)被導(dǎo)入。Swift的Array橋接了Oc的NSArray,但是這種橋接只有在數(shù)組類(lèi)型是可以橋接的時(shí)才可以。Oc中能成為數(shù)組元素的條件比于Swift既是寬松的又是嚴(yán)格的。NSArray的元素不一定都是一樣的類(lèi)型,另一方面Oc的數(shù)組元素必須是對(duì)象,這和Oc如何理解對(duì)象有關(guān)。一般地,如果它可以被向下轉(zhuǎn)型AnyObject,它就可以進(jìn)行橋接。這就是說(shuō)要不它是類(lèi),要不它是特殊的可以進(jìn)行橋接的結(jié)構(gòu)體,如Int、Double或String。

由此將Array傳遞給Oc是容易的。若你的Array的元素均可轉(zhuǎn)型AnyObject,那么你可以直接進(jìn)行傳遞。通過(guò)分配或者作為函數(shù)的參數(shù)。


46

若要在Swift的Array中調(diào)用NSArray的方法,你可以把它轉(zhuǎn)型為NSArray:


47

Swift的Array只要引用類(lèi)型為var聲明就是可改變的,而NSArray無(wú)論是聲明什么都是不可以改變的。NSMutableArray才是正解,它是NSArray的子類(lèi)。你無(wú)法轉(zhuǎn)型,分配,傳遞一個(gè)Swift Array到NSMutableArray。你需要先強(qiáng)制變換類(lèi)型。最好方法就是直接調(diào)用NSMutableArray 構(gòu)造器 init(array:),你可以直接將Array作為參數(shù)傳入。


48

將NSMutableArray變?yōu)锳rray,則可以用轉(zhuǎn)型(Cast),如果你想要一個(gè)原始Swift類(lèi)型的數(shù)組,你需要進(jìn)行兩次轉(zhuǎn)型:


49

如果一個(gè)Swift對(duì)象類(lèi)型無(wú)法轉(zhuǎn)型為AnyObject,那么他就無(wú)法橋接至Oc,如果你試著將一個(gè)包含該類(lèi)型實(shí)例的數(shù)組傳遞到需要NSArray的地方,編譯器就會(huì)阻止你。在這種情況,你需要自己進(jìn)行橋接。

比如有一個(gè)類(lèi)型是CGPoint的Array,雖然在Swift中沒(méi)有任何問(wèn)題,但是CGPoint是一個(gè)結(jié)構(gòu)體,在Oc中就無(wú)法使用,你也就不能將它放在NSArray中,如果你試著將它傳遞到需要NSArray的地方,就會(huì)有“[CGPoint]is not convertible to NSArray.”的錯(cuò)誤報(bào)告。對(duì)策是:將每個(gè)CGPoint包進(jìn)一個(gè)NSValue中(Oc的對(duì)象類(lèi)型,專(zhuān)門(mén)是非對(duì)象類(lèi)型的容器),這樣我們就可以有一個(gè)類(lèi)型是NSValue的數(shù)組,并可以提交給OC。


50

另一種情況就是,可選的Swift數(shù)組,Oc的集合類(lèi)型是不能包含nil的,畢竟在Oc中nil就不是一個(gè)對(duì)象。所以你就不能把這種包含可選值的數(shù)組直接傳給需要NSArray的地方。在傳遞之前,你需要做點(diǎn)事:如果可選值包含值,你可以先進(jìn)行解包,但是如果它不包含值,就沒(méi)法解包(nil)。對(duì)此,你可以用Oc的NSNull類(lèi),它的唯一實(shí)例就是NSNull( ),可以代表nil。因此對(duì)于一個(gè)可選值包著字符串的數(shù)組就可以在不是nil的元素上進(jìn)行解包,在是nil的地方進(jìn)行NSNull()代替。


51


現(xiàn)在再來(lái)談?wù)凮c的NSArray到了Swift的情形,這樣方向的橋接是沒(méi)有任何問(wèn)題的:NSArray可以很安全地變?yōu)锳rray。但是這樣轉(zhuǎn)變來(lái)的數(shù)組的類(lèi)型是什么呢?要知道NSArray并沒(méi)有帶著其元素的類(lèi)型信息。因此默認(rèn)地NSArray將會(huì)變成類(lèi)型是AnyObject的數(shù)組。

不過(guò)幸運(yùn)的是,從Xcode7開(kāi)始,Oc改變了其N(xiāo)SArray, NSDictionary, or NSSet這三種可橋接至Swift的集合類(lèi)型,使其變得能攜帶元素類(lèi)型信息了(OC叫這個(gè)是lightweight generic)。而在iOS9中,Cocoa API也修改為可以包含該信息。因此,絕大多數(shù)你從Cocoa接受的數(shù)組可以直接被識(shí)別類(lèi)型。

比如,這種簡(jiǎn)潔的代碼在以前是無(wú)法實(shí)現(xiàn)的:


52

其結(jié)果是一個(gè)包含字符串?dāng)?shù)組的數(shù)組,分類(lèi)列出了所有可用的字體。這在以前是不可能的,因?yàn)閁IFont的這兩種方法之前都是不可見(jiàn)的(他們以前會(huì)被認(rèn)為是AnyObject數(shù)組),而現(xiàn)在會(huì)被認(rèn)為是返回字符串?dāng)?shù)組的函數(shù)。

不過(guò)還是很有可能遇到從Oc接受AnyObject數(shù)組的情況的,如果真的遇到了,你就需要將其轉(zhuǎn)型或者變?yōu)槟撤N特定的Swift類(lèi)型。

下面就是一個(gè)Oc類(lèi)包含一個(gè)返回NSArray的方法(沒(méi)有被類(lèi)型標(biāo)記):


53

調(diào)用該方法并轉(zhuǎn)換結(jié)果,就需要將結(jié)果轉(zhuǎn)型為String的數(shù)組,


54

Oc的數(shù)組可以包含多種類(lèi)型的對(duì)象,不要強(qiáng)制將這種數(shù)組變?yōu)槠渲性夭荒苻D(zhuǎn)換的類(lèi)型,否則就會(huì)崩潰。對(duì)于這種情況要對(duì)癥下藥!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 01-常量與變量 學(xué)習(xí)swift第一步打印Hello World print("Hello World") swi...
    iOS_恒仔閱讀 5,369評(píng)論 2 19
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,043評(píng)論 4 61
  • 今天看了贏這本書(shū),由[美]杰克·韋爾奇著。主要講怎樣才能贏。全書(shū)總共分為五個(gè)部分,今天我只看了第一部分,第一部分是...
    YaoYiLin閱讀 359評(píng)論 0 1
  • 這周面臨著一個(gè)新機(jī)會(huì)的選擇,和處在不同位置的朋友們聊了聊,對(duì)每個(gè)人的感受也不盡相同。 有的人,讓你絕望,不想與之合...
    louise楊琴閱讀 337評(píng)論 4 1
  • 沿著清幽小徑 尋覓夢(mèng)中背影 草葉隨風(fēng)吟哦出闕闕戀歌 疏狂的虬枝剪碎了落日的幾許依戀 顫顫的流水鋪滿(mǎn)了我的相思 彼岸...
    眉清淺閱讀 360評(píng)論 0 2

友情鏈接更多精彩內(nèi)容