带有iOS中故事板的MVVMC

MVVM是MVC的替代品之一。 MVX模式未解决的缺点之一是视图导航。 MVVM也没有。 因此,提到了MVVMC。 C作为协调者是将导航与视图控制器分开。 使用MVVMC时,我们发现它将无法使用情节提要。 加入协调器后,诸如绑定,具有更好的可维护性的自动布局和可见性之类的所有好处都会消失。

原因是ViewController是调用performSegue并处理prepareForSegue那个。 如果我们想将这些方法转移到协调器上,我们需要找到一种方法来处理困难。 只要可以引用viewController,协调器就可以始终处理performSegue。 通过Apple文档,我们知道运行时的prepareForSegue 在segue创建之后且perform前调用。 为了在协调器中处理prepareForSegue ,我们需要在运行时进行一些技巧。 所以提出了一个问题。 我们是否要替换所有视图控制器的prepareForSegue ? 个人我更喜欢灵活性。 我不认为在所有情况下使用相同设计模式的整个应用程序都有意义。 另外,我不希望任何人只有在了解其工作原理后才能开始编码。 最好还是调用视图控制器的prepareForSegue 。 因此,我们可以认为视图控制器或协调器的prepareForSegue将首先被调用,或者我们可以认为一个是另一个的回调。 这导致使用毛毛雨。 通过这次采访,我们知道快速的动态编程不会很快到来。 似乎没有比迅速扑朔迷离的效果更好的方法了。 如果您发现我们不使用任何方法即可实现的任何方法,请发表评论。

因此,在需要协调器帮助时,让视图控制器可以采用一个协议。

 protocol Coordinated { 
var coordinationDelegate: CoordinationDelegate? { get set }
}

然后协调员应该处理方法

 protocol CoordinationDelegate { 
func prepareForSegue(segue: UIStoryboardSegue)
}

单一协调员

对于2个简单视图,假设我们要构建一个城市列表视图和一个城市详细信息视图。

MVVMC结构可以设计如下。 城市协调员创建城市视图模型和视图控制器。

因此,城市列表视图控制器和城市协调器分别采用协议。

 class MVVMCSCityListViewController: UITableViewController, Coordinated { 
var coordinationDelegate: CoordinationDelegate?
}
 extension MVVMCSCityCoordinator: CoordinationDelegate { 
func prepareForSegue(segue: UIStoryboardSegue) {
}

当用户在列表视图中选择一个城市时,该操作将发送回城市协调员,然后执行搜索

 extension MVVMCSCityCoordinator: MVVMCSCityListViewModelDelegate { 
func selectCity(viewController: UIViewController , city: City) {
selectedCity = city
viewController.performSegue(withIdentifier: “showDetail”,
sender: viewController)
}
}

现在我们可以拥有令人毛骨悚然的代码了。 仅当视图控制器采用协调协议时,才让协调器执行prepareForSegue 。 在应用启动时添加addCoordination,并且仅执行一次。

多协调员

大多数应用程序不仅会有一个场景。 让我们扩展一下简单的应用程序。 添加主屏幕。 我们可以从主屏幕转到列表视图或详细信息视图。 我们使用segue转到城市列表视图,并以经典的方式呈现详细信息视图。

家里再有一个故事板。 每个协调员代表一个情节提要。 因此,应用程序的结构如下所示。 我们添加了一个家庭协调器,一个家庭视图模型和视图控制器。 另外,我们添加了一个应用协调器来连接不同的协调器。

应用协调器负责初始化和引用所有其他协调器。 视图协调器初始化viewmodel和viewcontroller。 视图模型和视图控制器可能依赖于彼此引用的内容。 请注意保留周期。

为了连接协调员并使用情节提要,我们将需要添加一种机制来初始化城市协调员,并同时处理prepareForSegue 。 城市协调员应该是创建城市景观模型和视图控制器的人,因此在家庭协调员调用prepareForSegue时,将带有segue的请求传递给应用协调器是有意义的。 这可以像添加一个协议一样简单。

 协议HandleSegueDelegate:类{ 
func handleSegue(segue:UIStoryboardSegue)
}

只要所有协调员都采用此协议,我们就可以将segue从家庭协调员传递给应用程序协调员,然后再传递给城市协调员。 然后,城市协调员可以照常进行一些准备。

 扩展MVVMCSHomeCoordinator:CoordinationDelegate { 
func prepareForSegue(segue:UIStoryboardSegue){
如果segue.identifier ==“ showCityList” {
委托?.handleSegue(segue:segue)
}
}
}
 扩展AppCoordinator:HandleSegueDelegate { 
func handleSegue(segue:UIStoryboardSegue){
如果segue.identifier ==“ showCityList” {
让cityCoordinator = MVVMCSCityCoordinator(window:window)
协调员[kCityCoordinator] = cityCoordinator
cityCoordinator.delegate =自我
cityCoordinator.handleSegue(segue:segue)
}
}
}
 扩展MVVMCSCityCoordinator:HandleSegueDelegate { 
func handleSegue(segue:UIStoryboardSegue){
如果segue.identifier ==“ showCityList” {
//做一些准备
}
}
}

使用这种机制,我们可以链接所有不同的协调器并传递不在同一情节提要中的segue。 您可以在此处找到示例代码。