1. 程式人生 > >iOS中MVC之間的通訊

iOS中MVC之間的通訊

一, 所謂的 MVC 是指:
Model: 資料的擁有者,實現具體的業務邏輯。

View: 具體的使用者介面,如按鈕、列表、圖片。

Controller: 負責將 View 中使用者的動作傳達給 Model,將 Model 的資料通過 View 展現出來。

通常 iOS 的每個場景(scene)都由一個 ViewController 來管理,這個 ViewController

可以是庫中原生的,更多情況下是我們自定義的,但是都繼承自 UIViewController。顧名思義,ViewController 包含了

MVC 中的 Controller 和 View,其中的 View 一般是系統提供的 UIButton、UILabel 等類的例項。而

Model 一般都是我們自定義的類。

二 , MVC 之間的通訊

在這裡插入圖片描述

View 與 Controller
View 與 Controller 的關係是十分緊密的,他們之間可以雙向通訊。

Controller 可以直接操作 View。在使用 Storyboard

進行介面設計時,我們可以直接拖拽現有的控制元件(View),再通過 Controller—Drag 就可以為各種 控制元件生成一種類似於控制代碼的

outlet來作為 ViewController 的屬性,ViewController 通過 outlet 來對 View

進行操作,設定其外觀、狀態或者行為等等。如果是通過純程式碼來編寫介面,ViewController

類中就包含了控制元件的例項,直接通過這些例項的指標進行操作即可。

View 可以通過特殊的方式來發訊息給 Controller。因為系統自定義的 View 並不知道當用戶進行操作之後,Controller 需要做些什麼,為了減少耦合性,採用了一些特殊的方式來與 Controller 進行通訊。通訊的方式有:

IBAction。通過 Controller—Drag,XCode 會自動生成事件的響應方法。也可以使用(void)addTarget:(id)target action:(SEL)action方法來註冊事件的響應方法。

DataSource。當系統的某些 View 在呈現時需要我們提供相應的資料。我們必須為 View 指定

DataSource,並實現相應的 DataSourceProtocol(所謂的 Protocol

是指預先定義好的一組回撥函式,其中的部分是必須實現的,部分是可選的。)最典型的是 UITableView,我們必須告訴系統這個

TableView 有多少行,每行的 Cell 內容是什麼。

Delegate。它也是一組 Protocol,系統會在特定事件(如網頁的跳轉、網頁載入)發生的前後來呼叫這些方法。View 可以在不知道某個類的細節的情況下,把該類設定成自己的 Delegate,只要目標類實現了 Protocol 中的必須實現的方法。這些 Protocol 中的方法的命名是有規律的,通常會包含三種關鍵字:

will: 表示這個方法會在某種事件發生前呼叫。

did: 表示這個方法會在某種事件發生後呼叫。

should: 通常用來確定應不應該。如webView:shouldStartLoadWithRequest:navigationType:,它的返回值是布林型,當返回 NO 時,WebView 將不會載入內容。
Model 與 Controller
Controller 直接向 Model 請求資料。一般將 Model 的類作為 Controller 的屬性,直接呼叫相應的例項方法或者類方法即可。

Model 通過 Notification 和 KVO 將資料的變化通知給 Controller。KVO 是指 Key-value

observing,是一種觀察者模式的實現,可以使得 Controller 在 Model 的資料變化時能夠得到通知。Notification

是另外一種系統提供的通知機制,與 KVO 的直接通知到觀察者物件不同,系統提供了一個 NotificationCenter

來廣播通知。兩者都可以實現一對一或一對多的關係。

3️⃣Model 與 View

他們不能相互發送資訊。

三, View Controller 之間的切換

View Controller 之間的切換主要有三種方式:

Storyboard 的 segue。如果使用 Storyboard 來構建 App,那麼只需要 Ctrl-Drag 即可實現 View Controller 的切換,比如將一個按鈕 Ctrl-Drag 到另一個 View Controller 上。如果一個 segue 連結的是兩個 View Controller,那麼就需要用程式碼來完成跳轉,這個時候需要為 segue 來指定一個 Identifier,通過呼叫performSegueWithIdentifier:sender:來完成跳轉。

pushViewController:animated:方法。這個方法需要當前的 View Controller 在一個 UINavigationController 內部。UINavigationController 內部維護了一個棧來儲存其中的所有 View Controller,將新的 View Controller push 到棧內就可以完成跳轉。

presentViewController:animated:completion:方法。不同於上一種方法,這個方法並不是將 View Controller push 到棧內,而是維護一個 presenting 和 presented 關係。例如有兩個 View Controller 分別叫 A 和 B,如果 A 呼叫此方法來顯示 B,相當於 A擁有了 B。A 中的presentedViewController屬性會指向 B,B 的presentingViewController屬性會指向 A,這個關係是由系統自動維護的。

其中的第二種方法和第三種方法是類似的。他們之間的區別更多的是語義上的區別——presentViewController:animated:completion:方法更多的是在強調打斷現有的工作流,展現一組新的 View 來完成某個特定的工作,通常需要向用戶獲取某些資訊^1。它常常用來顯示一個模態的 View,一個模態的 View 通常有下面三個特點^2:

佔據整個螢幕,或者 iPad 上的整個 父View 的區域。

包含了完成一個任務所需的文字和控制元件。

通常有一個完成按鈕和一個取消按鈕,點選它們來表示任務的完成情況,並且退出當前的 View。

典型的場景:使用者登入、新增一項待辦事項。

另外一個值得注意的地方是,在寫 App 的時候有必要了解在各個狀態下,棧中的 View Controller 都有哪些,以避免重複地

push 同一個 View Controller。並且可以利用 UINavigationController 提供的一系列

pop*ViewController 的方法來快速到達指定的 View Controller。