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

iOS MVP模式下通过Segue在多ViewController间传值的问题咨询

问题解答

相关代码参考

class HomeVC: UIViewController {
    var homeData: [WorkoutModelInfo]= []
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "WorkoutDetailsViewController" {
            if let homeDetailVC = segue.destination as? HomeDetailsVC {
                guard let selectedIndex = sender as? Int else { return }
                let titleInSender = homeData[selectedIndex].workoutName
                homeDetailVC.presenter.convertData(homeData: home[selectedIndex])
            }
        }
    }
}

class HomeDetailsPresenter: class {
    var titleValue: String = ""
    var workoutDetailsData = [HomeDetailsData]()
    var dateOfWorkout: String = ""

    func convertData(workoutModel: WorkoutModelInfo) {
        var exercises = [ExerciseCellInNewWorkout]()
        for row in 0..<workoutModel.exercises.count {
            exercises.append(ExerciseCellInNewWorkout(opened: false, workoutModel: 
            workoutModel.exercises[row]))
        }
        workoutDetailsData = exercises
        titleValue = workoutModel.workoutName
        dateOfWorkout = workoutModel.workoutDate
    }
}

class HomeDetailsVC: UIViewController {
    lazy var presenter = HomeDetailsPresenter(homeDetailsPresenterDelegate: self)
    // 其他代码省略
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let destinationVC = segue.destination as? ThirdVC {
            destinationVC.workoutNameText = presenter.titleValue
            destinationVC.workoutDateText = presenter.dateOfWorkout
            destinationVC.data = presenter.workoutDetailsData
        }
    }
}

问题1:Segue的prepare方法中直接调用目标VC的presenter方法是否符合规范?

  • 结论:不符合规范,不推荐这么写

这种写法直接破坏了视图控制器的封装性,HomeVC强依赖了HomeDetailsVC的内部实现细节(内部持有presenter、presenter存在convertData方法),会导致两个模块耦合度过高:

  1. 后续如果HomeDetailsVC做架构重构,比如替换为MVVM架构移除presenter,或者修改convertData的方法名、参数,所有调用它的上游页面都要同步修改,维护成本极高
  2. 不符合「模块间仅通过公开接口交互」的设计原则,HomeDetailsVC的内部组件不应该对外暴露
  • 推荐优化方案:给HomeDetailsVC增加公开的接收参数属性,内部自行处理和presenter的交互:
// HomeDetailsVC 新增公开属性,隐藏内部实现
class HomeDetailsVC: UIViewController {
    // 对外仅暴露该接收参数,外部无需关注内部架构
    var workoutModel: WorkoutModelInfo? {
        didSet {
            guard let model = workoutModel else { return }
            presenter.convertData(workoutModel: model)
        }
    }
    lazy var presenter = HomeDetailsPresenter(homeDetailsPresenterDelegate: self)
    // 其他代码省略
}

// HomeVC的prepare方法简化为仅传公开参数
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "WorkoutDetailsViewController" {
        if let homeDetailVC = segue.destination as? HomeDetailsVC {
            guard let selectedIndex = sender as? Int else { return }
            homeDetailVC.workoutModel = homeData[selectedIndex]
        }
    }
}

问题2:MVP模式下直接从presenter读属性赋值给目标VC是否正确?

  • 结论:常规场景下是符合规范的,不需要额外加中间变量

MVP架构中,ViewController本身的核心职责就是和持有它的Presenter交互、获取展示数据、处理用户交互,所以VC直接读取Presenter的可公开访问属性完全符合架构设计要求,不需要多此一举在VC层存储冗余的中间属性。
只有满足以下场景时,才推荐在VC层声明变量、通过代理更新后再传递:

  1. 要传递的数据会在页面生命周期内动态变化,比如Presenter会异步请求更新标题、数据列表,需要确保跳转时拿到的是最新值,此时通过Presenter代理回调VC存储最新值更稳妥
  2. 数据需要在当前页面做二次处理/缓存,多次跳转都要用到同一个值,存在VC层可以避免重复从Presenter读取/处理
  • 注意点:你当前的写法没有把HomeDetailsVC的Presenter直接传递给ThirdVC,只是把数值赋值给ThirdVC的公开属性,不存在跨页面依赖Presenter的问题,完全符合分层原则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 18:39:03