菜鸟教程小白 发表于 2022-12-11 20:32:53

ios - 在协调器模式中重用 View Controller


                                            <p><p>我的 iOS 应用中有一个 ViewController 的流程 (<code>Flow A</code>)。流程 A 相当复杂(根据情况,一些 ViewController 会提前显示,或者根本不显示,等等)。为了处理这个问题,我使用了协调器模式。</p>

<p>代码(简化):</p>

<pre><code>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 &amp; UIViewController)) {
      viewController.coordinator = self
      self.navigationController.pushViewController(viewController, animated: true)
    }

    ...
}

class FirstViewController: UIViewController, FlowACoordinatable {

    var coordinator: FlowACoordinator?

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

....
</code></pre>

<p><code>FlowACoordinator</code> 包含有关如何以及何时使用 <code>present()</code> 方法呈现 ViewController 的逻辑。到目前为止一切顺利。</p>

<p>现在我有第二个流程,<code>Flow B</code>,与流程 A 大不相同。除了我想在两者之间共享一个 ViewController ,我们称之为 <code>SharedViewController</code>。这就是事情变得奇怪的地方,因为我不知道如何在两者之间共享这个 ViewController 。</p>

<p>问题:我有两种通信方式 - 协调器将自己设置为它呈现的 ViewController 的协调器,并且 ViewController 调用协调器上的方法作为对用户交互的响应。 <code>SharedViewController</code> 由两个 Coordinator 之一管理,并且它必须以某种方式将信息传递给当前的 Coordinator,无论它是哪一个。</p>

<p>到目前为止,我找到了两个解决方案,它们都不令人满意:</p>

<ol>
<li><p>一个额外的协调器只处理 <code>SharedViewController</code> - 这是很多开销并且很大程度上违背了协调器的目的。 </p></li>
<li><p>在 <code>SharedViewController</code> 中实现 <code>FlowACoordinatable</code>、<code>FlowBCoordinatable</code>、...,并具有多个协调器属性并在适当的时候调用它们次。还有很多开销、样板代码和对协调器的调用。</p></li>
</ol>

<p>关于如何很好地解决这个问题的任何想法?</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>我有同样的情况,我也不确定处理它的最佳方案是什么。我有一个必须在不同的协调器中使用的 viewController。</p>

<p>当给定的 viewController 本身不需要协调器时是可以的。例如,我们称它为 DisplayPopupViewController。
我创建了一个名为 CanDisplayPopupProtocol 的协议(protocol):</p>

<pre><code>protocol CanDisplayPopupProtocol {}

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

<p>然后在 Coordidnator1 中:</p>

<pre><code>extension Coordinator1: CanDisplayPopupProtocol{}
</code></pre>

<p>在 Coordinator2 中:</p>

<pre><code>extension Coordinator2: CanDisplayPopupProtocol{}
</code></pre>

<p>现在两个协调器都有 toDisplayPopupViewController() 方法。</p>

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

<p>但是在这种情况下,当需要为 viewController 分配一个协调器时,它会变得复杂得多,我传递的是哪个协调器?</p>

<p>我发现在我看来不是很优雅的解决方案是将 viewController 中的协调器类型更改为 Coordinator 协议(protocol),所以不要这样:</p>

<pre><code>weak var coordinator: Coordinator1?
</code></pre>

<p>我会用:</p>

<pre><code>weak var coordinator: Coordinator?
</code></pre>

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

<pre><code>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)
    }
}
</code></pre>

<p>这并不漂亮,而且还有另一个缺点。在 DisplayPopupViewController 中,每次我需要使用协调器的方法之一时,我都需要测试我使用的是哪种协调器类型。</p>

<pre><code>switch coordinator {
case is Coordinator1:
    (coordinator as! Coordinator1).toDisplayPopupViewController()
case is Coordinator2:
    (coordinator as! Coordinator2).toDisplayPopupViewController()
default: break
}
</code></pre>

<p>我确信这不是协议(protocol)的最佳用途,希望关注此线程的人能对这个问题有更好的解决方案。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 在协调器模式中重用 ViewController ,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/52169238/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/52169238/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 在协调器模式中重用 View Controller