ios - 使用 MVVM 时如何在 iOS 中处理导航

标签 ios mvvm

我已经将 ViewModels 引入到我最新的 iOS 应用程序中,但我在一些地方遇到了困难。想知道这里是否有人可以向我发送正确的方向。

基本上,应该如何/在哪里处理导航和错误对话框。

例如,目前我有一个注册过程,它由一个 RegistrationViewController 和一个 RegistrationViewModel 组成。当在 UI 中点击注册按钮时,会在 RegistrationViewModel 上调用注册方法。即来自 Controller 的 viewModel.register()

问题1:导航应该如何处理?
成功完成对 Web 服务的注册调用后,应用程序应根据某些业务逻辑导航到多个屏幕之一。目前,我通过调用导航管理器类在 ViewModel 中处理此问题。 Navigator.goToSuccessScreen()。这可以接受吗?我觉得这应该在 Controller 内部而不是通过 ViewModel 处理,但是所有用于确定导航到何处的业务逻辑都将在 View Controller 中完成。

问题2:如何显示错误对话框?
可以说上面的注册调用失败了。并且 UI 需要向用户显示 UIAlertView。可以调用 Navigator.displayError("some or other error message") 吗?还是应该再次将其路由回 Controller 以显示消息本身?

最佳答案

您可以使用路由枚举来处理它,并使其在 ViewModel 中可观察:

enum MoviesListViewModelRoute {
    case initial
    case showMovieDetail(title: String, overview: String, posterPlaceholderImage: Data?, posterPath: String?)
}

final class DefaultMoviesListViewModel: MoviesListViewModel {
        
    // MARK: - OUTPUT
    let route: Observable<MoviesListViewModelRoute> = Observable(.initial)
    ...
    func didSelect(item: MoviesListItemViewModel) {
        route.value = .showMovieDetail(title: item.title, 
                                       overview: item.overview, 
                                       posterPlaceholderImage: item.posterImage.value, 
                                       posterPath: item.posterPath)

}
从 View(viewController) 观察路由值并在值更改时显示它:
final class MoviesListViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        bind(to: viewModel)
        viewModel.viewDidLoad()
    }

    private func bind(to viewModel: MoviesListViewModel) {
        viewModel.route.observe(on: self) { [weak self] in 
            self?.handle($0) 
        }
    }

}

extension MoviesListViewController {
    func handle(_ route: MoviesListViewModelRoute) {
        switch route {
        case .initial: break
        case .showMovieDetail(let title, let overview, let posterPlaceholderImage, let posterPath):
            let vc = moviesListViewControllersFactory.makeMoviesDetailsViewController(title: title, 
                                                                                      overview: overview, 
                                                                                      posterPlaceholderImage: posterPlaceholderImage, 
                                                                                      posterPath: posterPath)
            navigationController?.pushViewController(vc, animated: true)
        }
    }

}

关于ios - 使用 MVVM 时如何在 iOS 中处理导航,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34673087/

相关文章:

c# - 依赖属性绑定(bind) usercontrol 与 viewmodel

ios - 如何更新静态库架构以支持 arm64 Build?

iphone - CCScale 不适用于 Sprite

ios - 以编程方式打开 native iOS铃声屏幕

IOS - 获取通知并决定做什么

.net - MVVM 没有意义吗?

c# - WPF - MVVM - 谁负责新的 DataProvider 连接?

ios - 如何在 map View 中拖动注释图钉?

c# - 将 DataGrid 列按日期排序

c# - RaisePropertyChanged 在另一个 View 模型中