Viper模块模板无视图关联,如何实现页面导航?
在未建立视图关联的Viper模板中实现页面导航
我下载了Viper模块模板,但该模板未建立视图关联,请问如何在此基础上实现页面导航?我是否可以通过简便方式获取视图引用?比如在Router中调用view.goToAnotherScreen这类定义在ViewController中的方法?
Scene Delegate 代码
let startModule = CardsCollectionRouter.createModule() let navigationController = UINavigationController(rootViewController: startModule) window?.rootViewController = navigationController window?.makeKeyAndVisible()
Router 代码
class CardsCollectionRouter: PresenterToRouterCardsCollectionProtocol { // MARK: Static methods static func createModule() -> UIViewController { let viewController = CardsCollectionViewController() let presenter: ViewToPresenterCardsCollectionProtocol & InteractorToPresenterCardsCollectionProtocol = CardsCollectionPresenter() let networkService = NetworkService() viewController.presenter = presenter viewController.presenter?.router = CardsCollectionRouter() viewController.presenter?.view = viewController viewController.presenter?.interactor = CardsCollectionInteractor(networkService: networkService) viewController.presenter?.interactor?.presenter = presenter return viewController } func showDescription(description: CharacterModel?) { let descriptionVC = DescripModuleRouter.createModule(description: description) //How to go on next screen?? let viewController = CardsCollectionViewController() viewController.navigationController?.pushViewController(descriptionVC, animated: true) } }
解决方案
1. 修复当前导航失效的问题
你现在的showDescription方法里新建了一个CardsCollectionViewController实例,这不是当前正在显示的控制器,所以navigationController会是nil,push操作自然不生效。正确的做法是让Router持有当前控制器的引用:
修改Router代码如下:
class CardsCollectionRouter: PresenterToRouterCardsCollectionProtocol { // 用weak避免循环引用 weak var viewController: CardsCollectionViewController? // MARK: Static methods static func createModule() -> UIViewController { let viewController = CardsCollectionViewController() let presenter: ViewToPresenterCardsCollectionProtocol & InteractorToPresenterCardsCollectionProtocol = CardsCollectionPresenter() let networkService = NetworkService() // 创建Router实例并绑定当前控制器 let router = CardsCollectionRouter() router.viewController = viewController viewController.presenter = presenter presenter.router = router presenter.view = viewController presenter.interactor = CardsCollectionInteractor(networkService: networkService) presenter.interactor?.presenter = presenter return viewController } func showDescription(description: CharacterModel?) { let descriptionVC = DescripModuleRouter.createModule(description: description) // 使用持有的当前控制器进行push viewController?.navigationController?.pushViewController(descriptionVC, animated: true) } }
2. 关于调用ViewController的自定义导航方法
这种方式是可行的,但不符合VIPER的职责划分——Router的核心职责就是处理页面导航逻辑,ViewController只应该负责视图渲染和把用户交互事件传递给Presenter。如果一定要这么做,在Router持有viewController引用后可以直接调用:
// 在ViewController里定义方法 extension CardsCollectionViewController { func goToAnotherScreen(_ vc: UIViewController) { navigationController?.pushViewController(vc, animated: true) } } // 在Router的showDescription里调用 viewController?.goToAnotherScreen(descriptionVC)
但还是更推荐让Router来处理导航,保持各模块职责清晰。
内容的提问来源于stack exchange,提问作者kesape
相关产品推荐
相关产品推荐

