【问题标题】:Multiple View Controllers in a single VIPER module单个 VIPER 模块中的多个视图控制器
【发布时间】:2021-11-14 20:10:41
【问题描述】:

我正在使用 VIPER 架构构建我的第一个应用程序。我有两个 VC:主要的一个和模态的一个(从主 VC 模态呈现)。我的模态VC中有一个tableView,当用户在那里选择一行时,我需要将它传递给presenter,然后从presenter传递给主VC。我还需要在模态 VC 中保持选定的行突出显示,所以如果我关闭它然后再次显示它,该行仍将突出显示。我很困惑,因为我不知道最好的方法是什么。我尝试将我的模态 VC 包含到配置器中并调用配置器两次:在主 VC 中,然后再次在模态 VC 中。它工作正常。这就是我的配置器的样子:

protocol ObserverConfiguratorProtocol {
    func configure(with mainViewController: ObserverViewController, with modalViewController: CurrenciesViewController)
}

class ObserverConfigurator: ObserverConfiguratorProtocol {
    
    func configure(with mainViewController: ObserverViewController, with modalViewController: CurrenciesViewController) {
        
        let presenter = ObserverPresenter(view: mainViewController)
        let interactor = ObserverInteractor(presenter: presenter)
        let router = ObserverRouter(view: mainViewController)
        
        mainViewController.presenter = presenter
        modalViewController.presenter = presenter
        
        presenter.interactor = interactor
        presenter.router = router
        presenter.view = mainViewController
        presenter.modalView = modalViewController
    }
    
}

主 VC 中的 viewDidLoad():

  override func viewDidLoad() {
        configurator.configure(with: self, view: CurrenciesViewController())
    }

模态VC中的viewDidLoad():

  override func viewDidLoad() {
        configurator.configure(with: ObserverViewController(), view: self)
    }

无论如何,我不确定它是否符合 VIPER 原则。是吗,还是有更好的解决方案?任何帮助表示赞赏!

【问题讨论】:

    标签: ios swift architecture viper-architecture


    【解决方案1】:

    如果你要展示另一个视图控制器,它应该在它自己的 VIPER 模块上。 ObserverViewController 不应该知道CurrenciesViewController 的存在。

    相反,只有ObserverRouter 应该知道如何构建CurrenciesModule 并呈现数据并将数据传递给它。像这样的:

    final class CurrenciesBuilder {
        @available(*, unavailable) private init() { }
    
        static func build(routerDelegate: ObserverRouterDelegate, selectedIndex: IndexPath?) -> CurrenciesViewProtocol {
            let service = CurrenciesService()
            let interactor = CurrenciesInteractor(service: service, selectedIndex: selectedIndex)
    
            let view = CurrenciesViewController(nibName: String(describing: CurrenciesViewController.self), bundle: nil)
            let router = CurrenciesRouter(vc: view)
            router.delegate = routerDelegate
    
            let presenter = CurrenciesPresenter(interactor: interactor,
                                                view: view,
                                                router: router)
            view.presenter = presenter
    
            return view
        }
    }
    

    因此,每当您需要呈现CurrenciesViewController 时,您可以传递selectedIndex,它可以突出显示它(如果适用)。我会将信息传递给交互者,并让演示者知道它并在视图中进行一些更改。

    为了将selectedIndex 传回ObserverViewController,您可以创建一个ObserverRouterDelegate,当CurrenciesViewController 将被解除时触发。

    protocol ObserverRouterDelegate: AnyObject {
        func didDismiss(with selectedIndex: IndexPath?)
    }
    

    总结;应该有 2 个模块,ObserverModuleCurrenciesModule,它们应该通过它们的路由器进行双向连接。由于路由器负责呈现/关闭视图(并且它们与它们的视图保持连接),它们可以更新它们的视图和/或让对等路由器更新它们自己的视图。

    【讨论】:

    • 感谢您的说明!正如你所说,我创建了两个模块,它按预期工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    • 2011-11-21
    • 2016-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    相关资源
    最近更新 更多