讓不懂程式設計的人愛上iPhone開發系列2 iOS12+Swift4.2版-Checklists-05
歡迎繼續我們的學習。
在上一課的內容中,我們已經成功的顯示出了表格,然後遺憾的是看不到其中有任何資料。
在本課的內容中,我們將一起學習如何完成這個偉大的使命。
哪怕地球在流浪,依然要努力~
表檢視代理
開啟專案,切換到ChecklistViewController.swift,然後在檔案的底部新增以下程式碼:
//MARK:- Table View Data Source override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 1 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "ChecklistItem", for: indexPath) return cell }
比起上一系列內容中的程式碼,這兩個方法看起來似乎有點嚇人。因為每個方法都有兩個引數,而且還返回了一個值。不過除了這種有點恐怖的形式之外,其實這兩個方法的作用跟我們之前所接觸過的並沒有什麼本質區別。
協議(Protocols)
以上兩個方法其實都屬於UITableView的data source 協議。
那麼什麼是協議呢?
首先來看作為法律術語的協議。在日常生活中,協議跟合同經常混用,指的是雙方通過法律認同的方式達成了某種共識,並需要在法律的框架下遵守。
此外,在技術領域,對網際網路比較熟悉的童鞋可能聽說過各種通訊協議,比如Ethernet協議、TCP/IP協議,UDP協議、Zigbee協議等等。這裡的協議指的是通訊雙方所必須遵從的一組約定,比如如何建立連線,如何相互識別,等等。
那麼在iOS開發中的協議又指的是什麼呢?
這裡的協議指的是某個類必須支援的一系列標準方法。通過設定這種協議,某個指定的類需要用一種特定的方式(指定型別的引數和返回值)來實現一系列的方法,但同時作為開發者又無需知道具體的實現細節。
通過使用協議,開發者可以給某個類新增某種特定型別的操作,比如這裡讓表檢視可以來處理資料。
data source(資料來源)是資料和表檢視之間的橋樑。通常來說,在iOS開發中檢視控制器會扮演資料來源的角色,並實現所需要的方法。因此,可以說檢視控制器就是表檢視的”代理“。
這就是所謂的代理模式-某個物件代表另外一個物件來完成某項任務。
表檢視需要知道它所需處理的資料行數,以及如何顯示某一行資料。但是我們並不能簡單的把一堆資料塞到表檢視的手裡,然後命令它,”表檢視,這裡有100行資料,幫忙把它們顯示在螢幕上吧。“
實際上,我們只能跟表檢視商量,“檢視控制器現在就是你的資料來源。所以,你最好問問它該怎麼顯示。”
而一旦表檢視關聯到某個資料來源上-比如這裡的檢視控制器,那麼它就會發送一個numberOfRowsInSection訊息,來詢問有多少行資料需要顯示。
而接下來表檢視會發送一條cellForRowAt訊息,向資料來源請求獲取某個具體的資料,從而顯示在cell裡面。
在iOS開發的學習中,我們將逐漸習慣看到這種模式:某個物件代替另外一個物件來完成某些任務。比如,在這裡ChecklistViewController將向表檢視提供所需的資料,不過前提是表檢視提出了這樣的請求~

在我們剛才所實現的第一個方法,也就是tableView(_: numberOfRowsInSection:)返回了一個數值1,它的作用是通知表檢視,只需要顯示一行資料。
在Swift語言中,return語句非常非常重要。
通過return語句,我們可以向方法的呼叫者回傳一個數據。比如在tableView(_:numberOfRowsInSection)這個放阿飛中,呼叫方法的是UITableView物件,它需要知道在表中究竟要顯示多少行資料。
方法體內的語句通常會利用例項變數以及從引數中所獲取的資料進行某些運算。當方法體內的程式碼執行完成後,return返回語句就會告訴系統,“任務完成,這裡是我得出的結論。”所返回的值通常被稱之為方法的結果。
對tableView(_:numberOfRowsInSection:) 這個方法來說,答案很簡單:只有一行資料需要顯示,因此返回1.
現在表檢視已經知道它需要顯示一行資料了,那麼接下來就需要呼叫第二個方法,也就是tableView(_:cellForRowAt:)
通過這個方法,表檢視獲取了一個原型cell的拷貝,然後將其返回給表檢視。可以看到,這裡再次用到了return語句。
在tableView(_:cellForRowAt:) 語句中,同時我們也會將行資料放入到cell中,不過目前應用中還沒有任何的資料。
好了,點選工具欄上的執行按鈕,可以看到介面上終於有了第一行資料。

小練習:
如果我們想讓表格中顯示五行資料,該怎麼辦呢?
狠簡單,
把tableView(_:numberOfRowsInSection:) 的返回值改為return 5就好了,試試看?~

理論知識:關於MVC
在結束本課之前,讓我們再充點電,瞭解下MVC模式。
實際上,在學習剛才的代理(delegate)和協議(protocols)用法的時候,可能很多童鞋都會質疑:
為什麼要這麼麻煩呢?為什麼要讓檢視控制器來提供資料,而不是乾脆讓表檢視自己給自己提供資料呢?這樣就不需要所謂的代理和協議了,多方便~
是啊?為什麼呢?
原因是,iOS應用的開發遵循非常嚴格的 MVC(Model-Vew-Controller) 模式。也就是模型-檢視-控制器模式。
在MVC模式下,表檢視只不過是一種純粹的視覺元素(也就是檢視),它不能也不應該和具體的資料扯上邊。資料通常是在Model那裡,我們只有通過controller檢視控制器這個橋樑把檢視和資料模型關聯起來。
如果你曾經學過其它程式語言和框架,會發現iOS的開發模式是最符合MVC的,邏輯上也是最清晰的。
那麼MVC模式有什麼好處呢?
MVC模式可以把業務邏輯(通常由controller負責)、資料(model)和介面顯示(view)嚴格區分開來,這樣在改進和個性化定製介面,或是對資料進行修改時,不需要把所有的內容都重寫。
此外,MVC模式允許使用各種不同的檢視來訪問同一個資料來源,並在不同的終端介面中使用。
其實除了在iOS開發中用到了MVC模式,在web開發中也經常用到MVC模式。
當然,除了經典的MVC架構模式,現在還有了幾種新的變種,比如MVP(model-view-presenter)、MVVM(Model-view-viewmodel)和Viper,感興趣的童鞋可以自行了解:
https:// en.wikipedia.org/wiki/M odel%E2%80%93view%E2%80%93viewmodel
https://www. objc.io/issues/13-archi tecture/viper/
最後要再次安利一下斯坦福大學的iOS開發公開課,裡面對MVC模式做了非常詳盡而直觀的解釋,強烈推薦e文好的童鞋前往觀看~