讀古今文學網 > iOS編程基礎:Swift、Xcode和Cocoa入門指南 > 13.5 模型-視圖-控制器 >

13.5 模型-視圖-控制器

Apple的文檔和其他地方都會提及術語:模型-視圖-控制器(簡稱為MVC)。這指的是一種架構目標,對於帶有圖形用戶界面的程序(用戶可以查看和編輯信息)來說,這個目標旨在實現程序在3個功能性方面的分離。MVC的概念可以追溯到Smalltalk的年代,從那以後關於它的介紹已經不勝枚舉,下面是對這3個術語的通俗解釋:

模型

數據及對數據的管理,通常稱為程序的「業務邏輯」,程序真正關注的核心部分。

視圖

用戶看到並與之交互的部分。

控制器

介於模型與視圖中間的協調部分。

考慮一個遊戲,當前的分數顯示在用戶眼前:

·向用戶展示當前遊戲分數的UILabel是個視圖;它只不過是個顯示而已,其業務知道如何繪製自身。它應該繪製什麼(即分數)取決於其他地方。

新手程序員會將UILabel所顯示的分數作為實際的分數:為了增加分數,他會讀取UILabel上的字符串、將其轉換為數字、增加該數字、將數字轉換回字符串,然後用該字符串替換掉之前的字符串。這完全違背了MVC哲學!呈現給用戶的視圖應該反映出分數,但不應該存儲分數。

·分數是個內部維護的數據;它是個模型。它可能會像擁有公開的increment方法的實例屬性那麼簡單,也可能像擁有大量方法的Score對像那麼複雜。

分數是個數字,而UILabel顯示的是個字符串;這足以表明視圖與控制器本質上是不同的。

·告訴分數何時應該變化,並在用戶界面上顯示出更新後的分數,這是控制器的職責。模型的數字分數會通過某種方式進行轉換以顯示給用戶,如果這麼想就很清晰了。

比如,假設UILabel顯示的分數內容是「The score is 20.」。模型會存儲並提供數字20,那麼短語「The score is...」來自於何處呢?控制器會將這個短語放到數字前並呈現給用戶。

這個簡單的示例(如圖13-1所示)能夠很好地說明MVC的優勢。通過這種方式進行分離,程序的不同部分可以在很大程度上獨自演化。需要使用不同的字體與大小展現分數嗎?修改視圖即可;模型與控制器不需要知道這些,只是按照之前那樣工作即可。想要修改分數前的短語嗎?修改控制器即可;模型與視圖不會發生任何變化。

圖13-1:模型-視圖-控制器

在Cocoa應用中遵循MVC尤為重要,因為Cocoa本身就遵循了MVC。Cocoa類的名字揭示出了底層的MVC哲學。UIView是個視圖;UIViewController是個控制器;其目的體現出了視圖應該顯示什麼的邏輯。第11章我們看到一個UIPickerView並沒有持有所要顯示的數據;它是從數據源獲得數據的。因此,UIPickerView是個視圖;由數據源所維護的數據則是個模型。

Apple的文檔是這樣表述的:真正的模型與真正的視圖應該是可重用的,它們可以遷移到其他應用中;控制器一般來說是不可重用的,因為它關注的是如何協調模型與視圖。

在我開發的一個應用中,我會下載一個XML(RSS)新聞種子並以表格形式將文章標題展現給用戶。XML的存儲與解析完全是模型的事情,因此是可重用的,我甚至都沒有編寫這部分代碼(使用了Kevin Ballard編寫的名為FeedParser的代碼)。表格是個UITableView,它顯然是可重用的,因為它來自於Cocoa。不過,當UITableView轉向我的代碼並詢問應該在單元格中顯示什麼時,我的代碼會轉向XML並請求與表格的這一行相對應的文章標題,這是控制器代碼,它只適用於這個應用。

MVC為應用中對像之間的可見性提供了答案。控制器對像通常要能看到模型對象與視圖對象。模型對像或模型對像組通常不需要看到外面。視圖對像通常不需要看到外面,不過諸如單例、數據源與目標-動作等結構化設置可以讓視圖對象與控制器通信。