真正的MVC

向iOS开发人员提出的最常见的采访问题之一是解释模型-视图-控制器(MVC)设计模式。 简而言之,M代表模型,V代表视图,C代表控制器。 控制器是视图和模型之间的中介。 例如,控制器可以告诉模型获取一些数据,然后模型检索数据,然后将数据发送回控制器,然后控制器告诉视图更新UI,但是视图从不与模型对话。

不幸的是,许多开发人员在实现时都在为这个概念而苦苦挣扎。 我们通常没有得到明确的区分,而是通常只得到2,有时是1。

为了解决此问题,许多人开始使用不同的设计模式,例如MPV,MVVM,Clean Swift(我最近遇到过)。 所有这些模式都试图解决相同的问题。 抽象,可重用性和易于测试。 但是,如果我告诉您MVC足以达到所需的抽象级别,并且足以使测试变得非常容易,并且每个组件都可以重复使用,该怎么办?

MVC的问题并不是MVC真正的问题,而是我们实现MVC的方式。 我已经看过并遍历了许多代码,其中视图控制器充满了使测试和可重用性变得异常困难的代码。 如果我们能够按预期真正使用MVC,那么我们应该能够实现我们的目标,因此称为“ True MVC”。 好的,足够多的讨论,让我们看一些真实的例子。

想象我们有一个简单但现实的问题。 我们正在构建一个员工目录应用程序。 我们的应用程序有2个屏幕。 第一个屏幕显示按字母顺序排序的员工列表,当在列表上点按员工时,它将导航到员工详细信息屏幕。 为了保持简短和简单,我们将简单介绍第一个屏幕。

对于“员工列表”屏幕,我们具有以下组件。 EmployeesController,EmployeesModel,EmployeesView和Employee故事板。 由于控制器充当视图和模型之间的中介,因此控制器将具有EmployeesModelEmployeesView的实例。

控制者

在我们的情节提要中,我们转到EmployeesController场景中的超级视图,转到身份检查器,然后将视图的类更改为EmployeesView。 然后,在控制器中创建一个插座。

  //视图实例 
@IBOutlet var employeeView:EmployeesView!
  //模型实例 
让employeeModel = EmployeeModel()

现在我们有了Model和View的实例,我们需要在controller-view,controller-model,model-controller,view-controller之间建立通信。 可以通过协议实现通信。 因此,我们需要4个协议。 控制器中为2,视图中为1,模型中为1。

  //控制器协议 
协议EmployeesControllerModelDelegate {
func getEmployees()
}
协议EmployeesControllerViewDelegate {
func updateTableViewWithData(员工:[员工])
}
  //查看协议 
协议EmployeesViewDelegate {
func didSelectEmployee(员工:雇员)
}
  //模型协议 
协议EmployeeModelDelegate {
func didGetListOfEmployees(员工:[员工])
}
  //然后我们相应地设置代表 
  //模型委托,以便控制器可以与模型对话 
var modelDelegate:EmployeesControllerModelDelegate? {
返回employeeModel
}
  //视图委托,以便控制器可以与viewvar viewDelegate对话:EmployeesControllerViewDelegate { 
返回employeeView
}
  //我们还需要遵守视图和模型委托 
employeeModel.delegate =自我
employeeView.delegate =自我
 扩展EmployeesController:EmployeeModelDelegate { 
func didGetListOfEmployees(员工:[员工]){
}
}
 扩展名EmployeesController:EmployeesViewDelegate { 
func didSelectEmployee(employee:Employee){
}
}

视图

让我们转到视图。 我们需要符合UITableViewDelegate,UITableViewDataSource和EmployeesControllerViewDelegate。 让我们看看它是什么样的。

 扩展名EmployeesView:EmployeesControllerViewDelegate { 
func updateTableViewWithData(员工:[员工]){
自雇人士=雇员
tableView.reloadData()
}
}

模型

我们的模型与视图非常相似。 我们只需要符合EmployeesControllerModelDelegate。

 扩展名EmployeeModel:EmployeesControllerModelDelegate { 
func getEmployees(){
//这可以是对服务器/核心数据的API调用
}
}

结论

你有它。 真正的MVC运作中。 我们所有的组件都很小,可重用和可测试。 您可以在下面下载源文件。 一定要看一下测试用例,看看使用True-MVC测试代码有多么容易。

西尔维斯/ True-MVC
通过在GitHub上创建一个帐户为True-MVC开发做出贡献。 github.com