我的iOS应用程序中有ViewController的流(Flow A)。流程A相当复杂(视情况而定,某些视图控制器显示得很早,或者根本没有显示,等等)。为了处理这个问题,我正在使用协调器模式。

代码(简体):

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包含有关如何以及何时使用present()方法呈现视图控制器的逻辑。到目前为止,一切都很好。

现在,我有第二个流程Flow B,它与流程A大部分不同。除了我想在两者之间共享视图控制器之外,我们将其称为SharedViewController。这是使事情变得奇怪的地方,因为我对如何在两者之间共享此视图控制器没有真正好的主意。

问题:我有两种通信方式-协调器将自己设置为它所提供的视图控制器的协调器,视图控制器在协调器上调用方法以响应用户交互。 SharedViewController是由两个协调器之一管理的,无论如何,它都必须以某种方式将信息传递给当前的协调器。

到目前为止,我发现了两个解决方案,它们都不令人满意:
  • 一个仅处理SharedViewController的附加协调器-这是很多开销,并且在很大程度上违反了协调器的目的。
  • FlowACoordinatable中实现FlowBCoordinatableSharedViewController,...,并且具有多个协调器属性,并在适当的时间调用所有这些属性。还有很多开销,样板代码和对协调员的调用。

  • 关于如何解决这个问题的任何想法?

    最佳答案

    我遇到的情况相同,我也不确定要解决的最佳方案是什么。我有一个必须在不同的协调器中使用的viewController。

    当给定的viewController本身不需要协调器时,就可以了。例如,我们将其称为DisplayPopupViewController。
    我创建了一个名为CanDisplayPopupProtocol的协议:

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

    然后在Coordidnator1中:
    extension Coordinator1: CanDisplayPopupProtocol{}
    

    在Coordinator2中:
    extension Coordinator2: CanDisplayPopupProtocol{}
    

    现在,两个协调器都具有toDisplayPopupViewController()方法。

    正如我之前所说的,当我不需要将协调器传递给viewController时,这很好,在这种情况下,DisplayPopupViewController不需要协调器,因为它将被关闭并且不需要任何导航。

    但是,在这种情况下,当需要将协调器分配给viewController时,它将变得更加复杂,我通过的协调器是哪一个?

    我发现我认为不是很优雅的解决方案是将viewController中的协调器类型更改为Coordinator协议,因此,而不是此:
    weak var coordinator: Coordinator1?
    

    我将使用:
    weak var coordinator: Coordinator?
    

    然后在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)
        }
    }
    

    这并不漂亮,还有另一个缺点。每次我需要使用一种协调器方法时,都需要在DisplayPopupViewController内测试我使用的是哪种协调器类型。
    switch coordinator {
    case is Coordinator1:
        (coordinator as! Coordinator1).toDisplayPopupViewController()
    case is Coordinator2:
        (coordinator as! Coordinator2).toDisplayPopupViewController()
    default: break
    }
    

    我确信这不是协议的最佳用途,希望遵循此线程的人将对此问题有更好的解决方案。

    关于ios - 在Coordinator模式中重用View Controller,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52169238/

    10-11 02:20