MVP模式下主视图控制器向详情视图控制器Presenter传值,此设计是否合理?
这个实现不算MVP模式下的良好设计,咱们来聊聊问题和优化方案
首先得明确MVP的核心原则:View层只和自己对应的Presenter交互,各模块的职责边界要清晰。你当前的写法有几个明显的问题:
- 打破职责边界,耦合度太高:主VC作为View层,直接去调用详情页Presenter的
set(data:)方法,相当于让主VC知道了详情Presenter的存在和内部方法。以后如果详情Presenter的方法签名改了,或者换了实现逻辑,主VC也得跟着改,维护起来会越来越麻烦。 - 可测试性变差:单元测试主VC的时候,你得模拟详情Presenter的实例,还要确保
set(data:)被正确调用,这额外增加了测试的复杂度,不符合MVP便于测试的初衷。 - 不符合分层思想:MVP的分层是View → Presenter → Model,跨View层直接操作对方的Presenter,等于跳过了分层的约束,时间久了代码很容易变成“面条代码”。
更合理的实现方案
方案1:通过详情VC的公共接口传递数据
这是最直接的优化方式:给详情VC加一个公开的属性或方法,主VC只负责把数据传给详情VC,由详情VC自己把数据交给它的Presenter。这样主VC只和同属View层的详情VC交互,完全符合MVP的分层原则。
示例代码:
// 主ViewController中的跳转代码 let detailVC = DetailViewController() detailVC.targetData = presenter?.data[row] // 只和详情VC交互 navigationController?.pushViewController(detailVC, animated: true) // 详情ViewController中的处理 var targetData: YourDataType? { didSet { presenter?.set(data: targetData) // 自己的View自己通知Presenter } }
方案2:用路由组件统一管理跳转(适合中大型项目)
如果项目页面较多,可以封装一个路由类,专门处理页面跳转和数据传递逻辑。主VC的Presenter告诉路由“我要跳详情页,带这个数据”,路由负责创建详情VC和它的Presenter,把数据注入进去,再完成跳转。这样主VC和详情模块完全解耦,所有导航逻辑都集中在路由里,维护起来更方便。
方案3:依赖注入(适合有DI框架的项目)
如果你们项目用了依赖注入框架,在创建详情Presenter的时候直接把需要的数据注入进去。主VC只需要触发跳转动作,不需要关心数据怎么传到详情Presenter手里,进一步降低耦合。
总的来说,MVP的核心就是各层各司其职,避免跨层越权操作。让View层只专注于和自己的Presenter交互,中间的跳转和数据传递要么交给同层的View,要么交给专门的中间组件,这样代码的可维护性和可测试性才会更高。
内容的提问来源于stack exchange,提问作者aneuryzm
相关产品推荐
相关产品推荐

