简体   繁体   English

在Coordinator模式中重用View Controller

[英]Reusing View Controller within Coordinator pattern

I have a flow ( Flow A ) of ViewController's in my iOS app. 我的iOS应用程序中有ViewController的流程( Flow A )。 Flow A is rather complex (depending on circumstances, some view controllers are shown early, or not shown at all, etc.). 流程A相当复杂(视情况而定,某些视图控制器显示得很早,或者根本没有显示,等等)。 In order to handle that I am using the coordinator pattern. 为了处理这个问题,我使用了协调器模式。

The code (simplified): 代码(简体):

protocol Coordinator {
    func start()
}

protocol FlowACoordinatable {
    var coordinator: FlowACoordinator
}

class FlowACoordinator: Coordinator {

    private var navigationController: UINavigationController

    private var firstVC: FirstViewController
    private var secondVC: SecondViewController

    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }

    func start() { ... }

    func present(_ viewController: (FlowACoordinatable & UIViewController)) {
        viewController.coordinator = self
        self.navigationController.pushViewController(viewController, animated: true)
    }

    ...
}

class FirstViewController: UIViewController, FlowACoordinatable {

    var coordinator: FlowACoordinator?

    func buttonTapped() {
        self.coordinator?.goToNextStep()
    }
}

....

FlowACoordinator contains logic about how and when to present view controller's using the present() method. FlowACoordinator包含有关如何以及何时使用present()方法呈现视图控制器的逻辑。 So far so good. 到现在为止还挺好。

Now I have a second flow, Flow B , mostly different from Flow A. Except I want to share a view controller between the two, let's call it SharedViewController . 现在,我有第二个流程, Flow B ,与流程A大部分不同。除了要在两者之间共享视图控制器之外,我们将其称为SharedViewController This is where things get strange, because I have no really good idea on how to share this view controller between the two. 这是使事情变得奇怪的地方,因为我对如何在两者之间共享此视图控制器没有真正的好主意。

The problem: I have a two way communication - the coordinator sets itself as the coordinator of the view controller it presents & the view controller calls methods on the coordinator as a response to user interaction. 问题:我有两种通信方式-协调器将自己设置为它所提供的视图控制器的协调器,视图控制器在协调器上调用方法以响应用户交互。 SharedViewController is managed by one of two Coordinators, though, and somehow it has to pass information to the current Coordinator, regardless of which one it is. SharedViewController是由两个协调器之一管理的,无论如何它都必须将信息传递给当前的协调器。

So far I found two solutions, both of them not satisfying: 到目前为止,我发现了两个解决方案,它们都不令人满意:

  1. An additional coordinator that handles just SharedViewController - this is a lot of overhead and largely defeats the purpose of Coordinators. 一个仅处理SharedViewController的附加协调器-这是很多开销,并且在很大程度上违反了协调器的目的。

  2. Implementing FlowACoordinatable , FlowBCoordinatable , ... in SharedViewController , and have multiple coordinator properties and call all of them at appropriate times. SharedViewController实现FlowACoordinatableFlowBCoordinatable ...,并具有多个协调器属性,并在适当的时间调用所有这些属性。 Also a lot of overhead, boilerplate code and calls to coordinators. 还有很多开销,样板代码和对协调员的调用。

Any ideas on how to solve this nicely? 关于如何解决这个问题的任何想法?

I am having the same situation and I am also not sure what is the best scenario to deal with it. 我也遇到同样的情况,我也不知道最好的解决方案是什么。 I have a viewController that must be used in different coordinators. 我有一个必须在不同的协调器中使用的viewController。

It is OK when the given viewController does not need a coordinator itself. 当给定的viewController本身不需要协调器时,就可以了。 For instance, let's call it a DisplayPopupViewController. 例如,我们称其为DisplayPopupViewController。 I create a Protocol called CanDisplayPopupProtocol: 我创建了一个名为CanDisplayPopupProtocol的协议:

protocol CanDisplayPopupProtocol {}

extension CanDisplayPopupProtocol where Self: Coordinator {
    func toDisplayPopupViewController() {
        let vc = DisplayPopupViewController.instantiate()
        navigationController.pushViewController(vc, animated: true)
    }
}

Then in Coordidnator1: 然后在Coordidnator1中:

extension Coordinator1: CanDisplayPopupProtocol{}

And in Coordinator2: 在Coordinator2中:

extension Coordinator2: CanDisplayPopupProtocol{}

Now both coordinator have the toDisplayPopupViewController() method. 现在,两个协调器都具有toDisplayPopupViewController()方法。

As I said before this is fine when I don't need to pass the coordinator to the viewController, in this case the DisplayPopupViewController does not need a coordinator, since it will be dismissed and do not need any navigation. 正如我之前所说,当我不需要将协调器传递给viewController时,这很好,在这种情况下,DisplayPopupViewController不需要协调器,因为它将被关闭并且不需要任何导航。

But it gets a lot more complex when there is a need to assign a coordinator to the viewController in this case, which os the coordinator I pass? 但是,在这种情况下,当需要将一个协调器分配给viewController时,它将变得更加复杂,我通过的那个协调器呢?

The solution I found which isn't very elegant in my point of view is to change the coordinator type in the viewController to the Coordinator protocol, so instead of this: 我发现在我看来不是很优雅的解决方案是将viewController中的协调器类型更改为Coordinator协议,所以代替此:

weak var coordinator: Coordinator1?

I will use: 我将使用:

weak var coordinator: Coordinator?

And then in the CanDisplayPopupProtocol I will test which coordinator I am dealing with and assign the correct coordinator to the viewController, like this: 然后在CanDisplayPopupProtocol中,我将测试我正在处理的协调器,并将正确的协调器分配给viewController,如下所示:

protocol CanDisplayPopupProtocol {}

extension CanDisplayPopupProtocol where Self: Coordinator {
    func toDisplayPopupViewController() {
        let vc = DisplayPopupViewController().instantiate()
        switch self {
        case is Coordinator1:
            vc.coordinator = self as? Coordinator1
        case is Coordinator2:
            vc.coordinator = self as? Coordinator2
        default: break
        }
        navigationController.pushViewController(vc, animated: true)
    }
}

This isn't pretty and there is another downside to it. 这并不漂亮,还有另一个缺点。 Inside the DisplayPopupViewController every time I need to use one of the coordinator's methods I need to test which coordinator type I am using. 每次我需要使用一种协调器方法时,都需要在DisplayPopupViewController内测试我使用的是哪种协调器类型。

switch coordinator {
case is Coordinator1:
    (coordinator as! Coordinator1).toDisplayPopupViewController()
case is Coordinator2:
    (coordinator as! Coordinator2).toDisplayPopupViewController()
default: break
}

I am sure this is not the best use of Protocols, hope someone following this thread will have a better solution for this problem. 我确信这不是协议的最佳用法,希望遵循此线程的人能够对此问题有更好的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 带协调器模式的 TabBar Controller - TabBar Controller With Coordinator Pattern 使用协调器模式时无法显示下一个视图 controller - Can't show next view controller while using coordinator pattern 如何通过协调器模式将值从第二视图控制器传递到第一视图控制器 - How to pass a value from second view controller to first view controller through coordinator pattern 在UISplitViewController中重用详细的视图控制器 - Reusing detailed view controller in UISplitViewController iOS Swift Coordinator 模式和导航控制器的后退按钮 - iOS Swift Coordinator pattern and back button of Navigation Controller 协调器模式没有推送到 NextViewController - coordinator pattern is not pushing to the NextViewController 正确的做法吗? 重用相同的故事板视图和视图控制器 - Correct way of doing it? Reusing same storyboard view and view controller 在导航控制器内部重用视图,并使用情节提要作为模式弹出窗口 - Reusing view inside navigation controller and as a modal popup with storyboards 在应用程序启动时查看协调器:我应该使用View Controller还是其他东西? - View coordinator on application startup: should I use View Controller or something else? iOS:容器视图控制器模式 - iOS: Container View Controller Pattern
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM