[譯]macOS 開(kāi)發(fā)-值綁定(Cocoa Bindings)(1)

譯自raywenderlich, 原標(biāo)題: Cocoa Bindings on macOS, 作者Andy Pereira
macOS 值綁定, 也就是Cocoa binding, 讓你不用浪費(fèi)時(shí)間寫(xiě)那些枯燥的代碼. 在使用 MVC 模式時(shí), 它會(huì)在控制器中自動(dòng)連接模型與視圖.
Cocoa Bindings的目標(biāo)就是盡可能少的編寫(xiě)代碼, 你實(shí)際使用過(guò)后就會(huì)發(fā)現(xiàn), 真好用!!
在這篇關(guān)于教程中, 你將學(xué)習(xí)編寫(xiě)一個(gè) Mac App, 它使用 iTunes API 在 App Store 搜索iOS App并展示出來(lái).
你會(huì)學(xué)習(xí)使用 Cocoa Binding 來(lái)做這些事情:

  • Interface Builder 中設(shè)置數(shù)據(jù)模型和 UI (如label, button)之間的關(guān)系
  • 設(shè)置某個(gè)默認(rèn)值
  • 應(yīng)用特定的數(shù)據(jù)格式, 如貨幣或日期格式
  • 更改數(shù)據(jù)結(jié)構(gòu), 例如: 將值轉(zhuǎn)換為某個(gè)顏色

開(kāi)始吧

雖然門(mén)檻很低, 但是在你還是需要先學(xué)會(huì)如何使用 Auto LayoutInterface Builder.
如果你已經(jīng)會(huì)這兩個(gè)工具了, 在這里下載我們創(chuàng)建好的基礎(chǔ)項(xiàng)目.
編譯運(yùn)行, 你會(huì)看到它已經(jīng)有一個(gè)基本的界面了, 但目前為止只是個(gè)空殼, 還沒(méi)有任何數(shù)據(jù).


你可以看到有幾個(gè)寫(xiě)好的 Swift文件

  1. iTunesRequestManager.swift 這個(gè)文件里面有一個(gè)結(jié)構(gòu)體, 結(jié)構(gòu)體有兩個(gè)靜態(tài)方法. 第一個(gè)方法將查詢發(fā)送到iTunes API, 會(huì)返回JSON格式搜索結(jié)果, 第二個(gè)是用于異步下載圖片的輔助方法.
  2. iTunesResults.swift, 定義了一個(gè)與iTunes的返回?cái)?shù)據(jù)相匹配的數(shù)據(jù)模型類.

注意: ** Result類中的所有變量都定義為dynamic. 這是因?yàn)榻壎ㄒ蕾囉阪I值編碼, 需要Objective-C運(yùn)行時(shí), 添加dynamic關(guān)鍵字可確保始終可用.
該類繼承自
NSObject**, 這也是綁定的要求. 當(dāng)你將一個(gè)變量添加到視圖控制器類時(shí), 你就知道為什么了.

使用 ITunes 搜索

首先, 你將通過(guò)iTunes API搜索, 并將結(jié)果添加到NSArrayController中.
打開(kāi) Main.storyboard 并查看 View Controller Scene中的對(duì)象. 你需要設(shè)置綁定的對(duì)象都有一個(gè)"(Bind)"標(biāo)記.

設(shè)置 NSArrayController

NSArrayController對(duì)象管理NSTableView的內(nèi)容, 通常采用模型對(duì)象數(shù)組的形式.

注意: NSArrayController提供的不僅僅是一個(gè)簡(jiǎn)單的數(shù)組, 包括管理對(duì)象的分節(jié), 排序和過(guò)濾.

打開(kāi)Main.storyboard. 在對(duì)象庫(kù)中找到一個(gè)NSArrayController對(duì)象, 并將其拖動(dòng)到文檔大綱中的視圖控制器場(chǎng)景分組下的對(duì)象列表中:


接下來(lái), 打開(kāi)assistant editor, 確保正在編輯的文件是ViewController.swift. 按住control鍵, 從 storyboard 中的Array Controller對(duì)象拖動(dòng)到ViewController.swift, 為其添加一個(gè)outlet, 命名為searchResultsController:

添加搜索按鈕事件

現(xiàn)在, 你可以使用搜索按鈕獲取搜索結(jié)果, 然后添加到searchResultsController里面.
按住control, 從storyboard中的搜索按鈕拖動(dòng)到ViewController.swift創(chuàng)建一個(gè)事件處理方法. 選擇創(chuàng)建一個(gè)Action并將其命名為searchClicked.



為searchClicked 添加以下代碼

//1
if (searchTextField.stringValue == "") {
  return
}
//2
guard let resultsNumber = Int(numberResultsComboBox.stringValue) else { return }
//3
iTunesRequestManager.getSearchResults(searchTextField.stringValue,
  results: resultsNumber,
  langString: "en_us") { results, error in
    //4
    let itunesResults = results.map { return Result(dictionary: $0) }
 
    //Deal with rank here later  
 
    //5
    DispatchQueue.main.async {
      //6
      self.searchResultsController.content = itunesResults
      print(self.searchResultsController.content)
  }
}

下面來(lái)一行一行分析代碼:

  1. 檢查文本字段; 如果它是空的, 就不要將該查詢發(fā)送到iTunes搜索API了.
  2. 獲取下拉列表中的值. 這個(gè)數(shù)字傳遞用于控制每一頁(yè)要返回多少個(gè)搜索結(jié)果. 下拉列表中有一些預(yù)設(shè)值, 也可以手動(dòng)輸入其他數(shù)字, 最多為200
  3. 調(diào)用 getSearchResults(_:results:langString:completionHandler:). 傳入每頁(yè)數(shù)量和搜索字符串. completionHandler 會(huì)返回結(jié)果或NSError.
  4. 這一行將 Dictionary 數(shù)組轉(zhuǎn)換為 Result 數(shù)組.
  5. 在你searchResultsController之前, 需要確保處于主線程. 可以使用DispatchQueue.main.async在主隊(duì)列執(zhí)行代碼. 雖然目前還沒(méi)有設(shè)置任何綁定, 但如果一旦有了, searchResultsController在當(dāng)前線程將同步更新NSTableView(和其他相關(guān)的UI 控件), 有一點(diǎn)需要記住就是更新 UI 必須在主線程操作.
  6. 最后, 設(shè)置 NSArrayController 的 content 屬性. NSArrayController有許多不同的方法來(lái)添加或刪除它管理的對(duì)象. 我們每次搜索的時(shí)候, 都需要清除以前的數(shù)據(jù), 并使用最新查詢的結(jié)果. 現(xiàn)在, 打印searchResultsController的內(nèi)容, 看看是否工作正常.
    最后, 添加一個(gè)ViewController的擴(kuò)展:
extension ViewController: NSTextFieldDelegate {
  func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
    if commandSelector == #selector(insertNewline(_:)) {
      searchClicked(searchTextField)
    }
    return false
  }
}

這段代碼會(huì)讓在用戶在輸入的時(shí)候中按回車鍵調(diào)用, 就像你點(diǎn)擊了搜索按鈕一樣.
編譯運(yùn)行, 在搜索欄中輸入flappy, 然后按回車鍵或單擊搜索按鈕. 你應(yīng)該在控制臺(tái)中看到以下內(nèi)容:


你的第一個(gè)綁定

來(lái)點(diǎn)干貨!
NSArrayController綁定到table view.
打開(kāi)Main.storyboard并選擇標(biāo)題為"Search Results Table View (Bind)"的table view. 打開(kāi)Bindings Inspector, 如下圖所示.
展開(kāi)"Table Contents"標(biāo)題下的"Content"選項(xiàng). 選中"Bind to"旁邊的復(fù)選框, 在右側(cè)的下拉框中選擇SearchResultsController, Controller Key設(shè)置為arrangedObjects


編譯運(yùn)行, 隨便搜索一個(gè)將你覺(jué)得返回大量的結(jié)果的關(guān)鍵字. 但是除非你更改了下拉列表中的數(shù)字, 否則最多只能看到五個(gè)結(jié)果, .
得益于數(shù)據(jù)綁定, NSArrayController 會(huì)自動(dòng)在table
view 中顯示內(nèi)容.

你會(huì)看到一堆重復(fù)的數(shù)據(jù), 因?yàn)閱卧裰械奈谋咀侄尾恢浪麄儜?yīng)該讀取的數(shù)據(jù)模型中的哪些屬性.

將文本字段綁定到屬性

打開(kāi)Main.storyboard并轉(zhuǎn)到View Controller Scene. 展開(kāi)table view中的對(duì)象, 找到名為T(mén)itle TextField(Bind)的text field. 選擇此對(duì)象并打開(kāi)綁定檢查器.
展開(kāi)"value"選項(xiàng)并綁定到"Table Cell View"對(duì)象. Model Key Path設(shè)置為objectValue.trackName.
objectValue是 table cell view 上的屬性, 其值由NSTableView從綁定數(shù)據(jù)確定.
在這個(gè)示例中, objectValue是對(duì)應(yīng)行的Result模型對(duì)象.

trackName
trackName

重復(fù)以上操作, 對(duì)Publisher TextField(Bind)進(jìn)行綁定, 綁定到objectValue.artistName.
編譯運(yùn)行, 并重新搜索. 你現(xiàn)在可以看到標(biāo)題和出版商了:

標(biāo)題和出版商
標(biāo)題和出版商

添加排名

可以看到排名列還是空的, 怎么做呢?從iTunes獲取的數(shù)據(jù)模型對(duì)象上沒(méi)有排名. 然而, iTunes搜索結(jié)果的順序是已知的.
只需要一點(diǎn)點(diǎn)代碼, 就可以設(shè)置排名了
在ViewController的//Deal with rank here later注釋下添加以下代碼:

.enumerated()
.map({ index, element -> Result in
  element.rank = index + 1
  return element
})

該代碼調(diào)用enumerated()以獲取索引和對(duì)象在索引. 然后, 它調(diào)用map(:_)為每個(gè)對(duì)象設(shè)置rank值, 并返回一個(gè)具有該結(jié)果的數(shù)組.
現(xiàn)在, 返回Main.storyboard, 選擇Rank TextField(Bind)并打開(kāi)Bindings Inspector. 在" value"部分中, 綁定到"Table Cell View". Controller Key 留空, model Key Path 設(shè)置為 objectValue.rank.
編譯運(yùn)行, 現(xiàn)在第一列中將會(huì)顯示排名:



現(xiàn)在, 你需要將Result用戶選擇的對(duì)象綁定到UI的其余部分.

最后編輯于
?著作權(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)容

  • *面試心聲:其實(shí)這些題本人都沒(méi)怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,667評(píng)論 30 472
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,838評(píng)論 4 61
  • 很多年前,當(dāng)我剛剛出社會(huì)的時(shí)候,看過(guò)一本時(shí)尚雜志,一篇專題內(nèi)容,是關(guān)于,大齡職業(yè)女人,在職業(yè)上升期間,也在年齡增長(zhǎng)...
    葉公子閱讀 560評(píng)論 8 6
  • 母乳喂養(yǎng)的益處,我并不是一開(kāi)始就意識(shí)到。甚至在懷著諾諾時(shí),我還曾與部門(mén)同事一起爭(zhēng)論母乳喂養(yǎng)多長(zhǎng)時(shí)間比較好。 我清楚...
    醒來(lái)么么閱讀 757評(píng)論 0 0
  • 屋孤四壁白,窗外靜入懷。 昂首識(shí)天際,烏中一點(diǎn)白。 欲斫月中桂,奈何獨(dú)徘徊。 月本故鄉(xiāng)明,心卻任我行。
    心灑長(zhǎng)空閱讀 282評(píng)論 2 4

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