【问题标题】:Passing data between ViewModels in MVVM-C在 MVVM-C 中的 ViewModel 之间传递数据
【发布时间】:2021-01-08 01:47:36
【问题描述】:

我正在使用带有 Coordinator 的 MVVM 来设计应用程序。我怀疑的一件事是如何在不同的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)
    }

}

我当然可以在MainViewModel 中为CreateAccountViewController 创建ViewModel,并在createAccount 方法中将ViewModel 作为参数传递,但在这里这样做是否正确?这里的单元测试意味着什么?

【问题讨论】:

  • 据我了解,视图模型应该只是应用程序模型和视图之间的中介。如果应用程序模型是有保证的事实来源,则两个视图模型应该不需要相互了解。

标签: ios swift mvvm dependency-injection coordinator-pattern


【解决方案1】:

理想情况下,您不希望两个 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)
    }
}

更进一步,您可以为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 触发showAccountshowAccount 创建一个子协调器,等等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-02
    • 2019-01-12
    • 2022-07-29
    • 1970-01-01
    • 2021-05-12
    • 2020-03-03
    • 2015-12-19
    • 2015-01-20
    相关资源
    最近更新 更多