亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Swift > 正文

初步理解Swift中的泛型

2020-03-09 17:50:24
字體:
供稿:網(wǎng)友
這篇文章主要介紹了初步理解Swift中的泛型,是Swift入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
 

如果你已經(jīng)動手寫過Swift的程序,相信你已經(jīng)了解了Swift語言的知識,比如如何寫類(class)和結(jié)構(gòu)體(struct)。但Swift可沒這么簡單,呵呵呵。這篇教程主要講述Swift的一個強(qiáng)力的特性:泛型。這個特性在很多程序設(shè)計語言里都非常受歡迎。

對于類型安全(type-safe)語言,一個常見的問題就是如何編寫適用于多種類型輸入的程序。想象一下,兩個整型數(shù)相加和兩個浮點數(shù)相加的程序看起來應(yīng)該非常類似,甚至一模一樣才對。唯一的區(qū)別就是變量的類型不同。

在強(qiáng)類型語言中,你需要去定義諸如addInts, addFloats, addDoubles 等方法來正確地處理參數(shù)及返回值。

許多編程語言已經(jīng)解決了這個問題。例如,在C++中,使用Template來解決。而Swift,Java和C#則采用了泛型來解決這個問題。泛型,也是這篇文章要重點介紹的。

在這篇文章中,你將會學(xué)到Swift中如何使用泛型,也許你已經(jīng)接觸過,也許沒有,不過沒關(guān)系,我們會來一一探索。然后,我們會創(chuàng)建一個Flicker圖片搜索應(yīng)用,這個應(yīng)用使用了自定義的泛型數(shù)據(jù)結(jié)構(gòu)來保存用戶搜索的內(nèi)容。

備注:本文假設(shè)你已經(jīng)對Swift有基本的了解或者有過Swift開發(fā)經(jīng)驗。如果你第一次接觸Swift或者對Swift不是太了解,建議你首先閱讀下other Swift tutorials。

泛型介紹

也許你不知道這個術(shù)語,但相信你已經(jīng)在Swift中見到它了。Swift中的數(shù)組和字典類型就是使用泛型的經(jīng)典例子。

Object-C開發(fā)者已經(jīng)習(xí)慣使用數(shù)組和字典去保存多種數(shù)據(jù)類型。這種方式提供了很大的靈活性,但是誰又能知道一個API返回的數(shù)組里面到底是啥(數(shù)據(jù)類型)呢?你唯一能做的就是查看文檔或者查看(方法的)變量命令(這也是另外一種文檔喲?。?。即使你查看了文檔,你也不能保證程序在運(yùn)行期不產(chǎn)生bug或者其他異常。

相比Object-C,Swift中的數(shù)組和字典都是類型安全的。一個Int型數(shù)組只可以保存Int而不可以保存String。這意味著你不用再查看文檔啦,編譯器就可以幫你做類型檢查,然后你就就快可以愉快地coding了!


例如,在Object-C的UIKit中, 在自定義的View里面處理觸摸事件可以這么寫:
 

復(fù)制代碼代碼如下:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;

 

上述方法里面的set只可以保存UITouch實例, 因為文檔里面就是這么說的。由于這個集合里面可以放任何對象,所以你需要在代碼里面進(jìn)行類型轉(zhuǎn)換,也就是說把touches里面的對象轉(zhuǎn)為UITouch對象。

當(dāng)前Swift的標(biāo)準(zhǔn)庫里面沒有定義集合對象,但是你可以使用數(shù)組來代替集合對象,你可以用swift重寫上面的代碼:
 

復(fù)制代碼代碼如下:
func touchesBegan(touches: [UITouch]!, withEvent event: UIEvent!)

 

上面的代碼明確告訴你 touches數(shù)組只可以包含 UITouch實例, 否則編譯器就會報異常。這樣一來,你就再不用去做那煩人的類型轉(zhuǎn)換了,因為編譯器給你做了類型安全檢查,保證數(shù)組里面只允許有 UITouch對象。


簡要說來,泛型為類提供了一個類型參數(shù)。所有的數(shù)組都有相同的作用,即按順序儲存變量的數(shù)值,泛型數(shù)組除了多了一個類型參數(shù)之外,沒有其他的不同之處?;蛟S這樣想更容易理解:你將要應(yīng)用在數(shù)組上的各種算法和儲存的數(shù)值類型無關(guān),因此這些算法對于泛型數(shù)組和非泛型數(shù)組都適用。

既然你已經(jīng)明白了泛型的基礎(chǔ)知識和用法,那我們就開始把它應(yīng)用在一個具體的例子上吧。
泛型實例

為了測試泛型,你將會編寫一個在Flickr上搜索圖片的應(yīng)用。

首先請下載這個程序雛形,并盡快熟悉里面主要的類。其中Flickr類用于和Flickr的API交互。請注意這個類里面包含了一個API key(通常用于用戶授權(quán)—譯者注),但如果你想要擴(kuò)展這個應(yīng)用的話可能需要用自己的key,注冊請點我。


構(gòu)造并運(yùn)行這個應(yīng)用,你會看到這個:

初步理解Swift中的泛型

好像什么都沒有?別急,用不了多久你就可以讓它幫你抓取可愛的喵圖了!
有序字典(原文Ordered Dictionaries)

你的應(yīng)用會根據(jù)每個用戶的查詢情況下載圖片,按照圖片被搜索到的頻率由高到低排序并顯示。

但如果用戶對同樣的關(guān)鍵字搜索了兩次會怎樣?如果這個應(yīng)用能顯示上次搜索的結(jié)果就好了。

或許用數(shù)組來實現(xiàn)這個功能也行得通,但為了學(xué)習(xí)泛型,你將會使用一個全新的數(shù)據(jù)結(jié)構(gòu):有序字典。


和數(shù)組不同的是,包括Swift在內(nèi)地很多編程語言和框架都不保證集合(sets)和字典(dictionaries)的數(shù)據(jù)存儲順序。有序字典和普通的字典類似,不同之處在于它的key是有序的。你將會用這個特性,根據(jù)搜索關(guān)鍵字按順序存儲搜索結(jié)果。這樣存儲的好處是可以快速查詢并更新圖片列表。

一個草率的想法是自定義一個數(shù)據(jù)結(jié)構(gòu)處理有序字典。但是你需要更加有前瞻性才行!你必須考慮到如何讓你的應(yīng)用在未來幾年內(nèi)都能正常工作!因此在這里使用泛型再合適不過了。
初始數(shù)據(jù)結(jié)構(gòu)

點擊“文件/新建/文件...”新建一個文件,并選擇“IOS/Source/Swift File”。點擊“下一步”并把這個文件命名為“OrderedDictionary”。最后,點擊“創(chuàng)建”。

你會得到一個空的Swift文件,加這樣一段代碼進(jìn)去:
 

復(fù)制代碼代碼如下:
struct OrderedDictionary {  }

 

到現(xiàn)在為止應(yīng)該都沒有什么問題。通過語義可以看出這個對象是一個結(jié)構(gòu)體。


注意:總之,值的語義可以想象為“復(fù)制、粘貼的行為”,而不是“分享、參考的行為”。值的語義帶來一系列的好處,例如不用擔(dān)心一段代碼無意地修改你的數(shù)據(jù)。了解更多,點擊"Swift by Tutorials"的第三章節(jié):類和結(jié)構(gòu)體。

現(xiàn)在你需要將其一般化,以便它能夠裝載你需要的任何類型的數(shù)據(jù)。通過下列改變你對Swift中“結(jié)構(gòu)”的定義:
 

復(fù)制代碼代碼如下:
struct OrderedDictionary<KeyType, ValueType>

 

在尖括弧中的元素是通用類型的參數(shù)。KeyType和ValueType不是他們自身的類型,而是你可以使用在結(jié)構(gòu)里定義取代的類型?,F(xiàn)在就簡潔清新許多了!

最簡單的實現(xiàn)一個有順序的字典是保持一個數(shù)組和一個字典。字典中將會裝載衍射,而數(shù)組將裝載keys的順序。


在結(jié)構(gòu)體內(nèi)部的定義中,加入以下的代碼:
 

復(fù)制代碼代碼如下:
typealias ArrayType = [KeyType]typealias DictionaryType = [KeyType: ValueType] var array = ArrayType()var dictionary = DictionaryType()

 

這樣聲明有兩個目的,就像上例描述的,有兩種類型的用于給已經(jīng)存在的類型的取新的名稱的別名。在這,你將分別地為后面的數(shù)組和字典賦值了別名。聲明別名是將復(fù)雜類型定義為更短名稱的類型的一種非常有效的方式。

你將注意怎么樣從結(jié)構(gòu)體中定義用“KeyType”和“ValueType”的參數(shù)類型中替換類型。上例的"KeyTypes"是數(shù)組類型的。當(dāng)然這是沒有這樣的類型的“KeyType”;當(dāng)在一般的實例化時,將替代Swift像對OrderedDictionary的類型的一切類型通過。

就因為這樣,你將會注意到編譯錯誤:
 

復(fù)制代碼代碼如下:
Type 'Keytype' does not conform to protocol 'Hashable'

 

或許你會詫異怎么會這樣?請再觀察下Dictionary的繼承者:
 

復(fù)制代碼代碼如下:
struct Dictionary<KeyType: Hashable, ValueType>

 


除了在KeyType之后的HashTable, 其他的都和OrderedDictionary的定義特別的相似。在分號后面為KeyType聲明的Hashable,一定符合Hashable的協(xié)議。這是因為字典需要為hash key實現(xiàn)。

用這種方式約束泛型參數(shù)是非常常見的。例如,你想要依據(jù)你的應(yīng)用使用參數(shù)做什么,來約束值的類型以,確保相等性、可打印性協(xié)議。

打開OrderedDictionary.Swift,用下例來取代你對結(jié)構(gòu)體的定義:
 

復(fù)制代碼代碼如下:
struct OrderedDictionary<KeyType: Hashable, ValueType>

 

這樣為OrderedDictionary聲明KeyType,必須符合Hashable。這就意味著,無論KeyType變成什么類型,都可以接受為沒有聲明的字典的KEY。

這樣,文件再次編譯,將不會報錯!

Keys, Values 和所有的這些趣事

如果不能為字典添加值,那么字典有什么作用了?打開OrderedDictionary.swift,在你的結(jié)構(gòu)體定義中添加以下函數(shù):
 

復(fù)制代碼代碼如下:
// 1mutating func insert(value: ValueType, forKey key: KeyType, atIndex index: Int) -> ValueType?{
  var adjustedIndex = index
   // 2
  let existingValue = self.dictionary[key]
  if existingValue != nil {
    // 3
    let existingIndex = find(self.array, key)!     // 4
    if existingIndex < index {
      adjustedIndex--
    }
    self.array.removeAtIndex(existingIndex)
  }   // 5
  self.array.insert(key, atIndex:adjustedIndex)
  self.dictionary[key] = value
   // 6
  return existingValue}

 

下面介紹一些新的特性。讓我們一步一步來介紹:

  •     插入一個新對象的方法,insert(_:forKey:atIndex),需要三個參數(shù):一個特別的key的值,插入一對key-value的索引。這是你之前沒有注意到的一個關(guān)鍵字:改變。
  •     結(jié)構(gòu)體的設(shè)計是默認(rèn)不變的,這意味著通常你在實例化的方法中,不能改變結(jié)構(gòu)的成員變量。這十分有限,你能添加改變的關(guān)鍵字,并告訴編譯器這個方式在結(jié)構(gòu)體中是允許改變的。這將幫助編譯器做出決定什么時候復(fù)制結(jié)構(gòu)體(他們是寫時復(fù)制的),也有助于API的編檔。
  •     你為字典的索引器輸入一個如果已經(jīng)存在,那么返回已存在的值的key,這個插入方法模擬字典更新值相同的行為,因此為這個值保持已經(jīng)存在的值。
  •     如果這有一個已經(jīng)存在的值,只有這樣函數(shù)才能為這個值在數(shù)組里找出索引。
  •     如果這個已經(jīng)存在的key在插入索引的之前,這時你需要調(diào)整插入的索引,因為你需要移除已經(jīng)存在的key。
  •     你將適當(dāng)?shù)馗聰?shù)組和字典。
  •     最后,你返回已存在的值,當(dāng)這或許沒有已存在的值,這個函數(shù)返回一個可選的值!


現(xiàn)在你可以為字典添加移除值?

像下列對OrderedDictionary結(jié)構(gòu)體的定義的函數(shù):
 

復(fù)制代碼代碼如下:
// 1mutating func removeAtIndex(index: Int) -> (KeyType, ValueType){
  // 2
  precondition(index < self.array.count, "Index out-of-bounds")   // 3
  let key = self.array.removeAtIndex(index)   // 4
  let value = self.dictionary.removeValueForKey(key)!   // 5
  return (key, value)}

 

現(xiàn)在再讓我們一步一步分析:

1.這是改變結(jié)構(gòu)體狀態(tài)的函數(shù),removeAtIndex的名稱需要和數(shù)組的方法匹配。恰當(dāng)?shù)臅r候,考慮使用鏡像系統(tǒng)庫中API是不錯的選擇。這樣幫助開發(fā)者在他們的工作平臺里,非常容易地使用你的API。

2.首先,你需要檢查索引,觀察他們是否是在大量的數(shù)組里。嘗試著從未聲明的數(shù)組中移除越位的元素,將會導(dǎo)致超時錯誤,所有在這時檢查將會更早符合這樣的情況。你或許在Objective-C中使用斷言函數(shù);在Swift中斷言也是可使用的。但是前提是在釋放的工程中是活動的,否則你運(yùn)行的應(yīng)用的將會終止。

3.接著,當(dāng)同時從數(shù)組中移除值時,你在給定的索引中數(shù)組中獲得值。

4.然后,你從字典中為這個key移除的值,同時也會返回這個值?;蛟S在給出的key中,字典也沒有相應(yīng)的值,所以removeValueForKey返回一個可選的。這種情況下,你知道字典將會為給出的key,包含一個值,因為這是唯一的自己給字典添加值的方法--insert(_:forKey:atIndex:),這時你可以選擇使用“!”,表明這將會有正義感值。

5.最后,你在一個元組返回的key和value。數(shù)組的removeAtIndex和字典的removeValueForKey是一樣的返回已存在的值功能。

值的讀取跟寫入

把值寫入字典(dictionary)是沒問題了, 可是這樣還不夠! 你還需要實現(xiàn)一個方法(method) 從字典中讀出相應(yīng)的值.

打開 OrderedDictionary.swift 文件, 然后把下列代碼添加到結(jié)構(gòu)定義(struct definition)當(dāng)中, , 就放在 thearrayanddictionaryvariable 聲明的下面:
 

復(fù)制代碼代碼如下:
var count: Int {
  return self.array.count}

 

這個常用的屬性, 用來算出字典里面有幾條記錄. 只要返回數(shù)組的 count 屬性的中值就可以了!

接下來, 就是如何訪問(Access)字典中的記錄了(Element). 我們可以通過下標(biāo)(Subscript)來訪問, 代碼如下:
 

復(fù)制代碼代碼如下:
let dictionary = [1: "one", 2: "two"]let one = dictionary[1] // Subscript

 

下標(biāo)的語法我們會用了, 但是如果是我們自己定義的類那該怎么用呢? 好在 Swift 支持在自定義類里頭添加這項功能. 而且實現(xiàn)起來也不復(fù)雜.


把下列代碼添加到結(jié)構(gòu)定義的底部:
 

復(fù)制代碼代碼如下:
// 1
subscript(key: KeyType) -> ValueType? {
  // 2(a)
  get {
    // 3
    return self.dictionary[key]
  }
  // 2(b)
  set {
    // 4
    if let index = find(self.array, key) {
    } else {
      self.array.append(key)
    }     // 5
    self.dictionary[key] = newValue  
  }
}

 

我們詳細(xì)解釋下這段代碼:

  •     上面代碼注釋中標(biāo)有 1 的那一段:跟 func 和 var 類似, subscript 也是個關(guān)鍵字, 通過它定義下標(biāo).  參數(shù) key 是出現(xiàn)在中括號中的那個對象.
  •     注釋中標(biāo)有 2 的那一段: 下標(biāo)由 setter 跟 getter 兩部分組成. 本例同時定義了 setter (代碼中的 set  ) 跟 getter (代碼中的 get ). 當(dāng)然, 不是每個下標(biāo)都要同時定義 setter 跟 getter.
  •     注釋中標(biāo)有 3 的那一段: getter 比較簡單, 只要通過參數(shù) key, 在字典中找到相應(yīng)的值即可. 字典返回的是可選值(optinal), 如果 key 不存在, 該值為 nil.
  •     注釋中標(biāo)有 4 的那一段: setter 就復(fù)雜些. 首先要檢測這個 key 在有序字典里面是不是已經(jīng)存在. 如果不存在, 則把 key 添加到數(shù)組中. 由于我們需要把 key 添加到數(shù)組的尾部, 所以這里調(diào)用的是 append 方法.
  •     注釋中標(biāo)有 5 的那一段: 把值添加到字典中. 這里用隱性命名的變量 newValue 獲取傳遞過來的值.

就像用 Swift 自帶的字典類的下標(biāo)那樣去, 你可以通過 key 來查找某個值. 可是如果我們需要像訪問數(shù)組那樣, 用下標(biāo)索引(index)訪問某個值, 該怎么辦呢? 既然是有序字典, 沒有道理不能通過下標(biāo)索引一個一個的按順序訪問.


結(jié)構(gòu)體跟類可以定義多個參數(shù)類型不同的下標(biāo)(subscript). 把下列代碼添加到結(jié)構(gòu)定義的底部:
 

復(fù)制代碼代碼如下:
subscript(index: Int) -> (KeyType, ValueType) {
  // 1
  get {
    // 2
    precondition(index < self.array.count, 
                 "Index out-of-bounds")     // 3
    let key = self.array[index]     // 4
    let value = self.dictionary[key]!     // 5
    return (key, value)
  }}

 

這段代碼跟前面那段類似, 不同的是參數(shù)類型變成了 Int. 因為我們現(xiàn)在要實的功能是現(xiàn)像數(shù)組那樣, 使用下標(biāo)索引訪問有序字典. 不過這次返回的是由 key 跟 value 組成的一個元組(tuple). 因為有序字典就是由這樣一個一個的元組構(gòu)成的.

下面具體解釋下這段代碼:

  •     這個下標(biāo)只定義了 getter. 當(dāng)然你也可以把 setter 加上. 不過要注意先檢查 index 會不會越界.
  •     index 的值不能超出數(shù)組的界限, 也就是字典元組的個數(shù). 我們可以利用 precondition 提示開發(fā)人員, 程序出現(xiàn)越界訪問.
  •     用 index 從數(shù)組中讀出 key.
  •     再用 key 從字典中讀取 value. 需要注意的是, 由于數(shù)組中的每一個 key 跟字典的 value 是一一對應(yīng)的, 所以這里使用符號 ! (unwrapped) 對讀出來的 value 拆包.
  •     最后, 返回一個包含 key 和 value 的元組.


挑戰(zhàn): 為上面那個下標(biāo)實現(xiàn) setter . 可以參考前面的例子.
提示 1  


 注意, newValue 是個包含 key 跟 value 的元組.

 
提示 2  


 下列代碼可以將值從元組中提取出來:
 

復(fù)制代碼代碼如下:
let(key, value) = newValue

 

 

也許你會好奇, 如果 KeyType 是 Int 型的, 會出現(xiàn)什么問題? 使用泛型的好處是, 不管是什么類型, 只要能算出哈希值(hashable)的就行,  所以 Int 當(dāng)然也能用.  問題是, 當(dāng) key 也是 Int 型的時候, 這倆個下標(biāo)該怎么區(qū)分呢?

這就需要我們給編譯器提供更多的類型信息. 讓它知道在什么時調(diào)用哪個下標(biāo). 比如我們定義的這兩個下標(biāo), 返回的類型不一樣. 如果你用 key-value 類型的元組給它賦值, 編譯器就會自動調(diào)用那個數(shù)組式(array-style )的下標(biāo).

在項目中測試

讓我們在實際項目中,實驗編譯推斷使用的下標(biāo)函數(shù),以及一般情況下,OrderedDictionary是怎么工作的。

通過點擊"文件"、"創(chuàng)建"、"文件",新建一個項目,依次選擇"IOS"、"Source"、"Playground",再點擊下一步。然后點擊創(chuàng)建。

你必須得這樣操作:復(fù)制和粘貼OrderedDictionary.swift整體到新建的項目中。因為不能在寫教程時你的應(yīng)用模型中”看見”代碼

注意:這有一個解決方法,可以取代復(fù)制、粘貼的方式。如果你需要將你應(yīng)用的代碼加入到一個框架中,你的項目將接受的你代碼,就像Corrine Krych指出的這樣。


現(xiàn)在,在你的項目底部加入下列的代碼:
 

復(fù)制代碼代碼如下:
var dict = OrderedDictionary<Int, String>()dict.insert("dog", forKey: 1, atIndex: 0)dict.insert("cat", forKey: 2, atIndex: 1)println(dict.array.description 
        + " : " 
        + dict.dictionary.description) var byIndex: (Int, String) = dict[0]println(byIndex) var byKey: String? = dict[2]println(byKey)

 

在側(cè)欄中(或者通過視圖/助理編輯/顯示助理編輯/),你將可以看到println()函數(shù)輸出的內(nèi)容:

初步理解Swift中的泛型

在這個例子中,字典有一個整數(shù)型的key,所以編譯器會審查被使用分配決定使用哪個下標(biāo)變量的類型。如果被使用的下標(biāo)是一個(Int, String)的byIndex,編譯器會匹配期望的返回值類型,使用數(shù)組類型的索引的下標(biāo)。

如果你想從一個 byIndex 或者 byKey的變量中,移除類型的定義。編譯器將會報錯,表明編譯器不知道使用哪一個下標(biāo)。


小貼士:由于編譯器是按照類型推理來工作的,所以需要明確地表示出類型。當(dāng)存在多個有相同的爭議的返回值類型的函數(shù)時,調(diào)用者需要具體化。需要注意:Swift中函數(shù),可以“建-破”改變。

通過在項目中,對有順序的字典的實驗中,你可以發(fā)現(xiàn)他的工作原理。在重返app之前,嘗試從中添加、移除、以及改變key和value的類型。現(xiàn)在,你可以在你的順序字典中讀、寫操作!但要小心你的數(shù)據(jù)結(jié)構(gòu)?,F(xiàn)在你可以通過app來感受其中的樂趣了!

添加圖片查找

現(xiàn)在是時候讓你回過頭來注意手中的app了。打開 MasterViewController.swift。在兩個@IBOutlets 的下面,添加下列變量的定義:
 

復(fù)制代碼代碼如下:
var searches = OrderedDictionary<String, [Flickr.Photo]>()

 

你或許在困惑,為什么Flickr.Photo的類型中有個句號。那是因為Photo是在Flickr類的內(nèi)部定義的類。在Swift中,這樣的層次結(jié)構(gòu)是非常有利的。它將有助于類的名稱簡短化。在Flickr的內(nèi)部,你可以單獨(dú)使用Photo類,因為上下文關(guān)系告訴了編譯器這是什么。這是順序化字典查詢用戶訂閱的Flickr的功能。真像你看到的,包含查詢的字符串,和Flickr.Photo數(shù)組,或是從Flickr API 中返回的照片。注意,你在尖括號里給出的key和value,將成為在具體實現(xiàn)中KeyType和ValueType的參數(shù)類型。


接下來,找到表格視圖數(shù)據(jù)源的tableView(_:numberOfRowsInSection:)方法,然后把它改為如下所示:
 

復(fù)制代碼代碼如下:
func tableView(tableView: UITableView, 
               numberOfRowsInSection section: Int) -> Int{
  return self.searches.count}

 

這個方法使用有序字典來告訴表格視圖有多少行。接著,找到表格視圖數(shù)據(jù)源的tableView(_:cellForRowAtIndexPath:)方法并把它改為如下所示:

復(fù)制代碼代碼如下:
 
func tableView(tableView: UITableView, 
               cellForRowAtIndexPath indexPath: NSIndexPath)
              -> UITableViewCell{
  // 1
  let cell = 
    tableView.dequeueReusableCellWithIdentifier("Cell", 
      forIndexPath: indexPath) as UITableViewCell   // 2
  let (term, photos) = self.searches[indexPath.row]   // 3
  if let textLabel = cell.textLabel {
    textLabel.text = "/(term) (/(photos.count))"
  }
  return cell}

 

這是你在這個方法中所做的:

1. 首先,從UITableView中挪出一個單元格。你需要把它直接轉(zhuǎn)換為UITableViewCell,因為dequeueReusableCellWithIdentifier仍舊返回AnyObject(id in Objective-C),而不是UITableViewCell。或許在將來,蘋果公司會利用泛型重寫這部分API。

2. 接著,用你給的下標(biāo)索引從指定的行獲取Key和Value,

3. 最后,適當(dāng)?shù)卦O(shè)置單元格的文本標(biāo)簽并且返回當(dāng)前單元格。


現(xiàn)在讓我們嘗嘗鮮。找到UISearchBarDelegate 的拓展,就像下列的代碼一樣,改變單例方法。
 

復(fù)制代碼代碼如下:

func searchBarSearchButtonClicked(searchBar: UISearchBar!) {
  // 1
  searchBar.resignFirstResponder()   // 2
  let searchTerm = searchBar.text
  Flickr.search(searchTerm) {
    switch ($0) {
    case .Error:
      // 3
      break    case .Results(let results):
      // 4
      self.searches.insert(results, 
                           forKey: searchTerm, 
                           atIndex: 0)       // 5
      self.tableView.reloadData()
    }
  }}

 

當(dāng)用戶點擊查詢按鈕時,這個方法將會被調(diào)用。下列就是在這個方法中,你正做的事:

1.你第一反應(yīng)是放棄使用查詢框以及鍵盤。

2.然后,你又會使用搜索框查詢你輸入的文字,為查詢的文字而使用Flickr類來尋找。Flickr的查詢方法是:查詢術(shù)語,關(guān)閉執(zhí)行查詢成功或者失敗。通過參數(shù)關(guān)閉:要不是錯誤,那就是結(jié)果。

3.在錯誤的情況下,不會發(fā)生任何事。但是你可以通過使用警報來提示錯誤,但是現(xiàn)在我們可以簡化這樣的操作。代碼需要在這時暫停會兒,告訴Swfit編譯器你的錯誤沒有任何反應(yīng)的動機(jī)。

4.如果查詢有效,將會在查詢結(jié)果中顯示相關(guān)的值。你將查詢的術(shù)語作為key加入到順序字典中。如果已經(jīng)在字典中存在了,將會把他放入到list的頂部,然后用最后的結(jié)果更新整個字典。

5.最終,由于你有新的數(shù)據(jù),將再次加載table view。

哇!你的app將可以用于查詢圖片了!


構(gòu)建并運(yùn)行app,做幾次查詢。你將會看到下面這樣的一些東西:

初步理解Swift中的泛型

現(xiàn)在再用與之前搜索詞不同的另外一個進(jìn)行查詢. 你將會看到它跳到了頂部:

初步理解Swift中的泛型

選擇一個查詢結(jié)果點擊去,你會發(fā)現(xiàn)它并沒有顯示照片?,F(xiàn)在是時候修復(fù)這個問題了!
給我看照片!

打開MasterViewController.swift 并找到 prepareForSegue. 將它修改成下面這樣:
 

復(fù)制代碼代碼如下:

override func prepareForSegue(segue: UIStoryboardSegue, 
                              sender: AnyObject?){
  if segue.identifier == "showDetail" {
    if let indexPath = self.tableView.indexPathForSelectedRow()
    {
      let (_, photos) = self.searches[indexPath.row]
      (segue.destinationViewController         as DetailViewController).photos = photos    }
  }}

 

這是用了同創(chuàng)建單元項時訪問被排好序的查詢結(jié)果字典一樣的方法. 盡管沒有使用關(guān)鍵詞(檢索詞), 你也可以用下劃線來顯示出元組的這個部分不需要被綁定到一個本地變量.


構(gòu)建并運(yùn)行app,做一次查詢?nèi)缓簏c進(jìn)去。你會看到像下面這樣的東西:

初步理解Swift中的泛型

你好,小貓貓! 你有沒有想要發(fā)出快樂的呼聲呢? :]



注:相關(guān)教程知識閱讀請移步到swift教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
精品国产一区二| 欧美一区影院| 毛片av免费观看| 人人干人人干人人干| 国模私拍国内精品国内av| 久久久国产精华液999999| 毛片网站在线免费观看| xfplay资源站夜色先锋| 亚洲欧美自拍另类| 九九热99久久久国产盗摄| 久久午夜无码鲁丝片午夜精品| 久久网福利资源网站| www.亚洲视频| 国产第一精品| 国产强被迫伦姧在线观看无码| 亚洲精品自拍视频| 李丽珍裸体午夜理伦片| 久草在线免费福利资源| 日本激情一区| 少妇高潮惨叫久久久久| 亚洲综合图区| 最近最新中文字幕在线| 伊人婷婷欧美激情| 欧美写真视频网站| 男女视频网站免费观看| 久久久久99精品成人片我成大片| 性做久久久久久久久| 亚洲麻豆国产自偷在线| 国产伦精品一区二区三区免费| 超碰97在线免费| 日本成人在线视频网址| 激情亚洲综合在线| 国产精品九九九九九九| 97精品国产露脸对白| 男男受被啪到高潮自述| 霍思燕三级露全乳照| 亚洲午夜激情影院| 国产一区二区久久久久| 日韩高清av在线| 91在线一区二区三区| 精品福利一区二区三区免费视频| 亚洲综合在线免费| 日韩毛片在线观看| 亚洲怡红院在线观看| 久久精品免费在线观看| 性一交一乱一色一免费无遮挡| 国产99久久精品一区二区300| 伪装者免费全集在线观看| 一区在线播放视频| 成人午夜sm精品久久久久久久| 1769免费视频在线观看| 向日葵污视频在线观看| 免费观看黄色的网站| 黄网站色大毛片| 少妇精品一区二区三区| 国产美女精品一区二区三区| 国产在线视频91| 欧美午夜在线一二页| 婷婷久久综合九色综合绿巨人| 日本人成精品视频在线| 又黄又免费的视频| 影音先锋5566资源站| 久久精品综合一区| 日韩精品视频网站| 狠狠色狠狠色综合日日五| 久草视频免费在线| bl在线肉h视频大尺度| 91极品尤物在线播放国产| 天天插天天射| www.亚洲免费| 欧美日韩免费观看一区| 亚洲欧美国产不卡| 日韩大片b站免费观看直播| 91av视频在线免费观看| 成人免费视频在线观看| 精品freesex老太交| 日本特级黄色片| 国产精品一级片在线观看| 日韩视频在线免费播放| 国模少妇一区二区三区| a级精品国产片在线观看| 国产精品网站在线观看| 伊人久久大香线蕉综合四虎小说| 性欧美在线视频| 国产精品久久久久久久久免费看| 欧美日韩在线观看一区二区| 亚洲AV无码成人精品区东京热| 疯狂欧美牲乱大交777| 99国产一区二区三精品乱码| 色先锋资源久久综合5566| 成人在线免费观看| 国产精品一区二区精品视频观看| 中文字幕视频在线| 中文字幕网址在线| 亚洲色图首页| 国产精品一区在线播放| 亚洲精品久久区二区三区蜜桃臀| 欧美激情一区二区三区不卡| 蜜桃视频涩涩| japanese23hdxxxx日韩| 欧美电影免费提供在线观看| 日韩一区二区精品视频| 一级毛片免费播放| 拍拍拍无挡免费播放视频在线观看| 欧美特大特白屁股xxxx| 精品麻豆av| 日韩国产亚洲欧美| 在线观看国产原创自拍视频| 色资源二区在线视频| 中文字幕人妻熟女人妻洋洋| 亚洲欧美日韩国产成人综合一二三区| 激情欧美一区二区三区| 国内精品久久久久久| 青青草91久久久久久久久| 一区二区久久| 免费无遮挡无码永久视频| 国产天堂第一区| 国产精品一区二区三区毛片淫片| 日本精品视频在线观看| av在线之家电影网站| 性欧美丰满熟妇xxxx性仙踪林| 日韩视频www| 麻豆一区二区麻豆免费观看| jizzyou欧美16| 日本免费一区二区六区| 人妻一区二区三区| 国产色婷婷亚洲99精品小说| 成年男人的天堂| **国产精品| 亚洲熟妇无码另类久久久| 波多野结衣大片| h网站视频在线观看| 中文字幕在线有码| 四虎影院成人| 久久中文字幕av一区二区不卡| 天天看天天干| 日韩综合在线| 久草在线资源视频在线观看| 成人激情黄色小说| 久久大胆人体| 国产女人水真多18毛片18精品视频| 91亚洲无吗| 亚洲精品欧美精品| 国产伦精品一区二区三区在线播放| 视频在线观看一区二区| 国产又黄又粗又爽| 国产厕所精品在线观看| 国产精品久久久午夜夜伦鲁鲁| 国产网站在线播放| 欧美激情国产日韩精品一区18| 日韩一区二区不卡视频| 无遮挡动作视频在线观看免费入口| 91黄色小视频| 成全视频全集| 亚洲一级影院| 国产精品jvid在线观看蜜臀| 新版中文字幕在线资源| 精品av中文字幕在线毛片| 日韩一二三区不卡在线视频| 久久亚洲一区二区三区四区五区高| 欧美国产精品人人做人人爱| 国产成人精品福利一区二区三区| 91九色国产社区在线观看| 国产精品成人一区二区三区夜夜夜| 国产伦理久久久| 蜜桃免费一区二区三区| 亚洲在线免费| 久久狠狠一本精品综合网| 美女视频黄频大全不卡视频在线播放| 一菊综合网成人综合网| 一区二区三区在线观看av| 国内在线免费视频| 日韩欧美一区二区三区| 久久国产在线观看| 一区高清视频| 久久麻豆一区二区| youjizz久久| 女人和拘做爰正片视频| 亚洲激情文学| 久久精品凹凸全集| 国产特黄在线| 日韩欧美三级在线| 亚洲日本电影| 午夜免费播放观看在线视频| 日韩成人av在线| 久久影院中文字幕| 亚洲精品国产美女| 欧美超级乱淫片喷水| 免费成人高清在线视频| 亚洲天堂自拍偷拍| 久久久亚洲精品石原莉奈| www.中文字幕久久久| 亚洲视频在线观看三级| 91精品国产电影| 国产精品网站在线| 精品国产乱码久久久久久图片| 影音先锋亚洲电影| 国产91精品青草社区| 在线免费av一区| 日韩av一二三四| 色尼玛亚洲综合影院| 成人a视频在线观看| 国产精品久久..4399| 久久久久88色偷偷| 黄页网站大全在线免费观看| 日韩簧片在线观看| 明星裸体视频一区二区| 国产精品19乱码一区二区三区| 欧美一区二区三级| 日本a在线播放| 日本在线视频一区二区三区| 欧美国产一二三区| 内射国产内射夫妻免费频道| www视频在线观看免费| 国产成人精品毛片| 宅男在线精品国产免费观看| 男人添女人下面免费视频| 成人动漫av| 男女激情免费视频| 国产喂奶挤奶一区二区三区| 欧美videofree性高清杂交| 美女视频一区二区三区在线| 天堂av一区二区三区| 老司机成人在线| 97精品资源在线观看| 国产精品aaaa| 日本成人黄色网| 久久精品视频网| 亚洲午夜精品久久久久久app| 国产精品每日更新| 国产欧美视频一区| 深爱激情久久| 亚洲精品男人| 毛片中文在线观看| 亚洲婷婷综合色高清在线| 亚洲综合一区二区| 国内精品一区二区三区四区| 在线观看免费黄色小视频| 国产精品igao网网址不卡| 97国产成人高清在线观看| 欧美精选视频一区二区| 不卡在线一区| 欧美成人一区二区三区电影| 亚洲婷婷国产精品电影人久久| 中文字幕人妻熟女人妻a片| 被弄出白浆喷水了视频| 高清成人在线| 97久久香蕉国产线看观看| 一本久道久久综合中文字幕| 亚洲av成人片色在线观看高潮| 国产精品久久久国产盗摄| 国产肉体ⅹxxx137大胆| 国产日韩在线免费| 麻豆乱码国产一区二区三区| 成人av男人的天堂| 黑人巨大精品欧美一区| 西瓜成人精品人成网站| 免费看黄色aaaaaa 片| 国产成人精品免高潮费视频| 成人亚洲免费| 中文字幕一区二区三区在线观看| 国产无遮无挡120秒| 成人激情av| 99久久精品国产麻豆演员表| 一级视频在线观看视频在线啦啦| 亚洲欧美日韩成人在线| 国产成人一区二区在线观看| 在线三级电影| 毛片网站在线观看| 国产精品免费观看久久| 345成人影院| 国产精品99精品久久免费| 中文不卡1区2区3区| 免费看av不卡| 亚洲人成在线观看一区二区| 永久久久免费浮力影院| 污片在线免费观看| 亚洲精品国产精品久久清纯直播| 99在线精品观看| 国产精品久久久免费看| 国产二区三区四区| 性做久久久久久久| 粉嫩av一区二区三区在线播放| 福利91精品一区二区三区| 欧美最猛黑人xxxx| 国产热re99久久6国产精品| 影音先锋可以看的网站| 欧美性猛交xxxx久久久| 亚洲午夜久久久久中文字幕| 久久久久亚洲综合| 国产美女被遭强高潮免费网站| 在线成人av影院| 最近中文字幕免费在线观看| 自拍自偷一区二区三区| 粗暴91大变态调教| 精品福利一区二区三区免费视频| 日韩女优av电影| 最近中文字幕在线免费观看| 少妇性bbb搡bbb爽爽爽欧美| 国产欧美日韩网站| 日本一区视频| www日韩大片| 国产三级按摩推拿按摩| 日本一区精品| 亚洲精品在线不卡| 日韩在线视频免费观看高清中文| 亚洲亚洲一区二区三区| 日本电影中文字幕| 好男人官网在线观看| 国产日韩欧美一二三区| 免费在线观看视频a| 亚洲欧美激情小说另类| 免费一级在线观看播放网址| 亚洲精品鲁一鲁一区二区三区| 欧美极品免费| 久精品在线观看| 日本不卡一区二区三区在线观看| 精产国品自在线www| 亚洲一区在线观看免费| 色先锋av资源| h视频在线观看免费网站| 日本视频网址| 亚洲 欧美 另类人妖| 精华区一区二区三区| 成年人小视频在线观看| 亚洲综合av网| 亚洲午夜久久久久久久久电影网| 国产综合福利在线|