2. Agenda
● Problems of MVC
● Introduction to Model-View-ViewModel (MVVM)
○ Model
○ View
○ Controller
○ View Model
○ Data Manager
● Implementation
● Reference
3. Model-View-Controller
● A proven pattern for organizing code in complex
application design
● Separates an application into three main logical
components: model, view, and controller
4. Realistic Cocoa MVC
● Cocoa MVC encourages you to write Massive View Controllers,
because they are so involved in View’s life cycle that it’s hard to
say they are separate.
5. Problems of MVC
● MVC frameworks tend to lead to Apps with
Massive View Controllers
● Network calls, persistence, view logic, and all
other sorts of code ends up in the Controller.
● This Makes Controller code
○ difficult to read
○ difficult to change
○ difficult to unit test
○ difficult to reuse
6. Model-View-ViewModel (MVVM)
● The MVVM treats the view controller as the View
● There is no tight coupling between the View and
the Model
7. Model
● The same responsibility as in MVC
● Used to represent a “model” of some set of data
● For example: a model of a date, event, or place
● This typically involves having an NSObject class file
with properties
○ Hold data about the model object
○ Possibly some business logic around that model object.
8. View
● Used to represent the user interface (UI) of the app
● This can include UIViews, UIButtons, UITableViewCells,
UICollectionViewCells and UIViews on a storyboard
● A view shouldn’t directly interact with data model objects
○ It should instead have a function that takes in a set of parameters
representing data
9. Controller
● Used to set up the UI of views and handle any user
interaction with these views
● Like views, the controller shouldn’t directly interact with
the data model objects
○ It should ask its view model to set up a view with data instead.
○ Any state and business logic of the view controller will be kept by its
view model
10. View model
● Used to represent a model of a view controller
● All state and business logic associated with a view
controller will be kept by its view model
● A view model will trigger all calls to send and receive
data (using data managers)
● The view model doesn’t know about the view controller
11. Data manager
● Used to make and handle all calls to get data
● JSON parsing and serialization of this data to data
model objects
● Cache data
● Hold any state related to the data
● A view model will trigger the data manager to make and
handle data calls
13. Data manager
class DataManager {
static let sharedInstance: DataManager = DataManager()
func getData(callback : ((result : [DataObject])->()){
//code to get data i.e. some rest call
//parse JSON and serialize to an array of data model objects
//return array of data model objects by calling the callback
parameter
callback(result: result)
}
}
14. View Model - Init
class ViewModel {
var reloadCollectionViewCallback : (()->())!
var dataArray = [DataObject]()
init(reloadCollectionViewCallback : (()->()) {
self.reloadCollectionViewCallback = reloadCollectionViewCallback
retrieveData()
}
...
}
15. View Model - Retrieve Data
class ViewModel {
var reloadCollectionViewCallback : (()->())!
var dataArray = [DataObject]()
...
func retrieveData(){
DataManager.SharedInstance.getData({ result in
self.dataArray = result
self.reloadCollectionViewCallback()
}
}
}
16. View Controller - Init View Model
class ViewController: UIViewController {
var viewModel : ViewModel!
override func viewDidLoad(){
super.viewDidLoad()
setupCollectionView()
viewModel = ViewModel(reloadCollectionViewCallback :
reloadCollectionViewData)
}
}
20. View Model - Number of Items in Sections
// class ViewModel {
var dataArray : [DataObject]!
let kNumberOfSectionsInCollectionView = 1
func numberOfItemsInSection(section : Int) -> Int {
return dataArray.count
}
func numberOfSectionsInCollectionView() -> Int {
return kNumberOfSectionsInCollectionView
}
//}
21. View Model - Set up the collection view cell
// class ViewModel {
func setUpCollectionViewCell(indexPath : NSIndexPath, collectionView :
UICollectionView) -> UICollectionViewCell {
let dataObject = dataArray[indexPath.row]
let cell =
collectionView.dequeueReusableCellWithReuseIdentifier(“cell”,
forIndexPath: indexPath) as! MyCollectionViewCell
cell.setupData(name: dataObject.name, address: dataObject.address)
return cell
}
22. View - Collection view cell
class MyCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var addressLabel: UILabel!
func setupData(name : String?, address: String?){
nameLabel.text = name ?? “”
addressLabel.text = address ?? “”
}
}
23. ViewController - Keep track of the index path of the selected cell
extension ViewController: UICollectionViewDelegate {
func collectionView(collectionView: UICollectionView,
didSelectItemAtIndexPath indexPath: NSIndexPath) {
viewModel.setSelectedCellIndexPath(indexPath)
performSegue(WithIdentifier: “toNextViewController”, sender:
self)
}
}
24. ViewController - Segue to a new view controller
//class ViewController: UIViewController {
override func prepareForSegue(segue: UIStoryboardSegue, sender:
AnyObject?) {
if segue.identifier == “toNextViewController” {
let nextVC = segue.destinationViewController as!
NextViewController
nextVC.viewModel =
viewModel.getNextViewControllerViewModel()
}
}
//}
25. View Model - The index path of the selected cell
//class ViewModel : NSObject {
var selectedCellIndexPath : NSIndexPath!
...
func setSelectedCellIndexPath(indexPath : NSIndexPath) {
selectedCellIndexPath = indexPath
}
//}
26. View Model - Initialize the next view controller’s view model
//class ViewModel : NSObject {
func getNextViewControllerViewModel() ->
NextViewControllerViewModel {
let dataObject = dataArray[selectedCellIndexPath]
let nextViewControllerViewModel =
NextViewControllerViewModel(dataObject: dataObject)
return nextViewControllerViewModel
}
//}
27. Summery
● The view controller should only be responsible for
displaying UI and handling user interaction.
● Business logic, state, and data handling should be taken
out of the view controller and put into the view controller’s
view model.
● Only view models and data managers are allowed to
directly touch data model objects
○ view controllers and views should not.
29. Reference
● The Swift Programming Language (Swift 3.0.1)
● Swift and Model-View-ViewModel in Practice
● Swift Tutorial: An Introduction to the MVVM Design Pattern
● MVVM in Swift