首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在协调器模式中重用视图控制器

在协调器模式中重用视图控制器
EN

Stack Overflow用户
提问于 2018-09-04 15:05:15
回答 1查看 1.2K关注 0票数 2

我在我的iOS应用程序中有一个视图控制器的流(IOS)。流A是相当复杂的(取决于环境,某些视图控制器会提前显示,或者根本不显示,等等)。为了处理这个问题,我使用了协调器模式。

守则(简化):

代码语言:javascript
复制
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,主要不同于flow A。但我想在两者之间共享一个视图控制器,让我们称之为SharedViewController。这是事情变得奇怪的地方,因为对于如何在两者之间共享这个视图控制器,我没有真正的好主意。

问题:我有一个双向通信--协调器将自己设置为它所呈现的视图控制器的协调器&视图控制器调用协调器上的方法,作为对用户交互的响应。然而,SharedViewController是由两个协调员中的一个管理的,它必须以某种方式将信息传递给当前的协调员,而不管它是哪一个。

到目前为止,我发现了两种解决方案,它们都不令人满意:

  1. 另外一个只处理SharedViewController的协调器--这是一种很大的开销,很大程度上违背了协调员的目的。
  2. 实现FlowACoordinatableFlowBCoordinatable,.在SharedViewController中,并具有多个协调器属性,并在适当的时候调用它们。还有很多开销,样板代码和对协调员的调用。

对如何很好地解决这个问题有什么想法吗?

EN

回答 1

Stack Overflow用户

发布于 2019-07-12 06:11:51

我有同样的情况,我也不知道什么是最好的方案来处理它。我有一个viewController,必须在不同的协调器中使用。

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

代码语言:javascript
复制
protocol CanDisplayPopupProtocol {}

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

然后在Coordidnator1中:

代码语言:javascript
复制
extension Coordinator1: CanDisplayPopupProtocol{}

在Coordinator2中:

代码语言:javascript
复制
extension Coordinator2: CanDisplayPopupProtocol{}

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

如前所述,当我不需要将协调器传递给viewController时,这很好,在这种情况下,DisplayPopupViewController不需要协调器,因为它将被取消,不需要任何导航。

但是,当需要为viewController分配协调器时,它会变得更加复杂--在本例中,我传递的协调器是哪个?

从我的观点来看,我发现的解决方案不是很优雅,就是将viewController中的协调器类型更改为协调员协议,而不是这样:

代码语言:javascript
复制
weak var coordinator: Coordinator1?

我将使用:

代码语言:javascript
复制
weak var coordinator: Coordinator?

然后在CanDisplayPopupProtocol中,我将测试我所处理的哪个协调器,并将正确的协调器分配给viewController,如下所示:

代码语言:javascript
复制
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内部,每次我需要使用协调器的方法之一时,我都需要测试我所使用的协调器类型。

代码语言:javascript
复制
switch coordinator {
case is Coordinator1:
    (coordinator as! Coordinator1).toDisplayPopupViewController()
case is Coordinator2:
    (coordinator as! Coordinator2).toDisplayPopupViewController()
default: break
}

我相信这不是协议的最佳使用,希望跟随这个线程的人会有一个更好的解决这个问题的方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52169238

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档