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

Clean Swift架构:无Segue的路由设计及数据传递实现咨询

在Clean Swift中替代Segue的Router设计方案

当然可以在Clean Swift架构里完全摆脱Segue来做视图控制器的导航和数据传递,而且有几种非常便捷的设计思路,同时完全可以不依赖Segue实现数据传递——这反而更贴合Clean Swift的单向数据流和分层解耦原则。

一、常用的无Segue导航方案

  • 直接实例化VC+属性/闭包传参:Router直接创建目标视图控制器的实例,通过属性赋值或者闭包回调传递数据,同时负责执行push/present等导航操作,这是最直观灵活的方式。
  • 协议驱动的导航:定义统一的导航协议,让Router遵守该协议,视图控制器只需要调用协议方法即可触发导航,不用关心具体的导航实现细节,进一步解耦VC和Router。
  • Presenter触发导航:严格遵循Clean Swift的分层,由Presenter处理业务逻辑后,调用Router的导航方法,Router负责执行具体的页面跳转和数据传递,符合架构的单向依赖原则。

二、最简完整示例

我们实现一个简单场景:从HomeViewController跳转到DetailViewController,传递一个User模型数据,全程不使用Segue。

1. 定义数据模型

struct User {
    let id: Int
    let name: String
}

2. 实现Router(协议+类)

// 定义导航协议,规范Router的行为
protocol HomeRoutingLogic {
    func navigateToDetail(with user: User)
}

class HomeRouter: HomeRoutingLogic {
    // 弱引用避免循环引用
    weak var viewController: HomeViewController?
    
    func navigateToDetail(with user: User) {
        // 直接实例化目标VC(如果是xib创建,可替换为init(nibName:bundle:))
        let detailVC = DetailViewController()
        // 直接给目标VC的属性赋值传递数据
        detailVC.user = user
        // 执行导航操作(这里用push,也可以换成present)
        viewController?.navigationController?.pushViewController(detailVC, animated: true)
    }
}

3. HomeViewController实现

class HomeViewController: UIViewController {
    var router: HomeRoutingLogic?
    // 模拟要传递的数据
    let sampleUser = User(id: 1, name: "John Doe")
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .lightGray
        title = "Home"
        
        // 初始化Router并关联当前VC
        router = HomeRouter()
        (router as? HomeRouter)?.viewController = self
        
        // 添加测试按钮(代码创建,无需Storyboard)
        let goToDetailBtn = UIButton(type: .system)
        goToDetailBtn.setTitle("Go to Detail", for: .normal)
        goToDetailBtn.addTarget(self, action: #selector(goToDetailTapped), for: .touchUpInside)
        goToDetailBtn.frame = CGRect(x: 100, y: 200, width: 200, height: 50)
        view.addSubview(goToDetailBtn)
    }
    
    @objc func goToDetailTapped() {
        // 调用Router的导航方法,传递数据
        router?.navigateToDetail(with: sampleUser)
    }
}

4. DetailViewController实现

class DetailViewController: UIViewController {
    // 接收传递过来的数据
    var user: User?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        // 使用传递的数据更新UI
        title = user?.name
        
        let infoLabel = UILabel(frame: CGRect(x: 50, y: 200, width: 300, height: 50))
        infoLabel.text = "User ID: \(user?.id ?? 0)"
        infoLabel.textAlignment = .center
        view.addSubview(infoLabel)
    }
}

进阶:贴合Clean Swift分层的写法

如果要严格遵循Clean Swift的Presenter驱动逻辑,可以把导航触发放在Presenter中:

// 定义Presenter协议
protocol HomePresentationLogic {
    func triggerDetailNavigation()
}

class HomePresenter: HomePresentationLogic {
    var router: HomeRoutingLogic?
    var user: User?
    
    func triggerDetailNavigation() {
        guard let user = user else { return }
        router?.navigateToDetail(with: user)
    }
}

// 修改HomeViewController的按钮点击方法
@objc func goToDetailTapped() {
    let presenter = HomePresenter()
    presenter.user = sampleUser
    presenter.router = router
    presenter.triggerDetailNavigation()
}

这样整个流程完全符合Clean Swift的分层职责:VC负责UI交互,Presenter处理业务逻辑,Router专注导航和数据传递,全程不需要依赖Storyboard的Segue。

内容的提问来源于stack exchange,提问作者Sazzad Hissain Khan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:53:27