You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MVVM结合RxSwift实现ViewController导航:求简便Segue跳转方案

MVVM + RxSwift 下更简便的 ViewController Segue 跳转方式?

提问内容:

我正在用 MVVM 架构结合 RxSwift 做开发,之前试过用 Coordinator 和 RxFlow 来处理 ViewController 之间的导航,但感觉有点重。想问问有没有更简便的方式,直接通过 RxSwift 来实现 ViewController 间的 Segue 跳转?

以下是我目前的常规实现代码:

viewModel.users.subscribe { model in
    self.walkthrough = WalkthroughModel(country: (model.element?.country)!, countryCode: (model.element?.countryCode)!,PhoneNumber:"")
    DispatchQueue.main.async {
        self.performSegue(withIdentifier: "Walkthrough_phone", sender: self)
    }
}.disposed(by: disposeBag)

回答:

当然有更简洁的方式!其实我们可以把 Segue 的触发逻辑和 RxSwift 的响应式流结合得更紧密,既符合 MVVM 的职责分离,又能减少冗余代码。下面给你两种实用方案:

方案1:封装 Rx 扩展,让跳转逻辑可复用

我们可以给 UIViewController 写一个 Rx 扩展,把 Segue 触发转化为可绑定的信号,这样 ViewModel 只需要输出跳转事件,ViewController 负责绑定响应就行,代码更清爽:

import RxSwift
import RxCocoa

extension UIViewController {
    // 无参数的Segue绑定
    func rx_performSegue(withIdentifier identifier: String) -> Binder<Void> {
        return Binder(self) { vc, _ in
            vc.performSegue(withIdentifier: identifier, sender: vc)
        }
    }
    
    // 带参数的Segue绑定,同时处理参数传递
    func rx_performSegue<T>(withIdentifier identifier: String, prepare: @escaping (T) -> Void) -> Binder<T> {
        return Binder(self) { vc, parameter in
            prepare(parameter)
            vc.performSegue(withIdentifier: identifier, sender: vc)
        }
    }
}

然后在你的 ViewController 里这么用:

// 先在ViewModel里定义一个跳转输出流(示例)
// let navigateToWalkthrough = PublishSubject<WalkthroughModel>()

// ViewController里绑定信号
viewModel.navigateToWalkthrough
    .observe(on: MainScheduler.instance) // 确保UI操作在主线程
    .bind(to: self.rx_performSegue(withIdentifier: "Walkthrough_phone") { [weak self] model in
        self?.walkthrough = model
    })
    .disposed(by: disposeBag)

这种方式的好处是把跳转逻辑模块化,后续其他页面的Segue跳转都可以复用这个扩展,而且ViewModel只负责业务逻辑和事件分发,完全不涉及UI操作,更贴合MVVM的设计。

方案2:直接优化现有代码,减少冗余

如果不想写扩展,也可以直接改造你现有的代码,解决冗余和安全问题:

viewModel.users
    .compactMap { $0 } // 自动过滤nil元素,避免强制解包
    .observe(on: MainScheduler.instance) // 统一指定主线程,不用手动写DispatchQueue
    .subscribe(onNext: { [weak self] model in
        guard let self = self else { return }
        // 这里直接用model的属性,不用强制解包
        self.walkthrough = WalkthroughModel(country: model.country, countryCode: model.countryCode, phoneNumber: "")
        self.performSegue(withIdentifier: "Walkthrough_phone", sender: self)
    })
    .disposed(by: disposeBag)

这里做了几个优化:

  • 用compactMap过滤掉nil的元素,避免后续强制解包崩溃
  • 用observe(on: MainScheduler.instance)统一切换到主线程,替代手动的DispatchQueue.main.async
  • 用[weak self]和guard let避免循环引用,代码更安全

为什么这些方式更简便?

  • 摆脱了在subscribe闭包里写大量UI逻辑的混乱,符合响应式编程的思想
  • 代码更安全,避免强制解包和线程切换的冗余代码
  • 第一种方案的扩展可以复用,后续新增跳转逻辑成本更低

内容的提问来源于stack exchange,提问作者Guru Charan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:43:28