ios - 在 MVVM-C 中的 ViewModel 之间传递数据
问题描述
我正在使用 MVVM 和 Coordinator 来设计应用程序。我怀疑的一件事是如何在不同的ViewModels
. 通常,前一个 viewModel 只会创建下一个 viewModel,并且只会在prepareforsegue
. 但是,既然我负责所有导航,我该如何实现呢?
Class AppCoordinator : NSObject, Coordinator, UINavigationControllerDelegate {
var childCoordinators = [Coordinator]()
var navigationController: UINavigationController
var dependencyContainer : MainDependencyContainer
func start() {
let vc = ViewController.instantiate()
vc.coordinator = self
vc.viewModel = dependencyContainer.makeMainViewModel()
navigationController.delegate = self
navigationController.pushViewController(vc, animated: true)
}
func createAccount() {
let vc = CreateAccountViewController.instantiate()
vc.coordinator = self
navigationController.pushViewController(vc, animated: true)
}
}
我当然可以创建ViewModel
for CreateAccountViewController
inMainViewModel
并将 theViewModel
作为参数传递给createAccount
方法,但在这里这样做是正确的方法吗?这里的单元测试含义是什么?
解决方案
理想情况下,您不希望两个 ViewModel 相互交互并保持两个元素分开。
处理它的一种方法是通过导航所需的最少数据。
class AppCoordinator : NSObject, Coordinator, UINavigationControllerDelegate {
var childCoordinators = [Coordinator]()
var navigationController: UINavigationController
var dependencyContainer : MainDependencyContainer
func start() {
let vc = ViewController.instantiate()
vc.coordinator = self
let viewModel = dependencyContainer.makeMainViewModel()
// for specific events from viewModel, define next navigation
viewModel.performAction = { [weak self] essentialData in
guard let strongSelf = self else { return }
strongSelf.showAccount(essentialData)
}
vc.viewModel = viewModel
navigationController.delegate = self
navigationController.pushViewController(vc, animated: true)
}
// we can go further in our flow if we need to
func showAccount(_ data: AnyObject) {
let vc = CreateAccountViewController.instantiate()
vc.viewModel = CreateAccountViewController(with: data)
vc.coordinator = self
navigationController.pushViewController(vc, animated: true)
}
}
更进一步,您可以创建一个特定的 Coordinator CreateAccountViewController
,它将使用这些数据进行初始化。该start()
方法将创建其 ViewController 所需的任何内容。
// we can go further in our flow if we need to
func showAccount(_ data: AnyObject) {
let coordinator = CreateAccountCoordinator(data: data, navigationController: navigationController)
coordinator.start()
childCoordinators.append(coordinator)
}
在最后一个示例中,协调器仅负责构建其视图并在需要时将基本信息传递给下一个协调器。viewModel 只暴露给它的视图,最终视图不知道两者。在您的情况下,这可能是一个不错的选择。
最后,您可以使用协议抽象进行测试,以确保performAction
触发器showAccount
、showAccount
创建子协调器等。
推荐阅读
- java - 如何在接口默认方法中对新对象创建进行单元测试?
- jenkins - 如何在 groovy 脚本中使用 CURL 命令
- kubernetes - Kubernetes Cron Job 在创建下一个计划之前终止 Pod
- javascript - 在页面离开时通过 AJAX 删除图像
- php - 我可以在 PHP 邮件发送功能中添加紧急状态,以便在用户收到密码时重置密码不会过期吗?
- python - 如何在 os.popen 中传递多个命令
- amp-html - 获取 amp-form 和响应标头的正确方法是什么?
- json - 使用正确的键值对将文本文件转换为 json
- html - 如何在 Jenkins 版本中放置 iframe 或其替代品。2.176.2?
- javascript - 溢出在单词的开头,或在后续文本的末尾,直到下一次出现