簡體   English   中英

在Coordinator模式中重用View Controller

[英]Reusing View Controller within Coordinator pattern

我的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是由兩個協調器之一管理的,無論如何它都必須將信息傳遞給當前的協調器。

到目前為止,我發現了兩個解決方案,它們都不令人滿意:

  1. 一個僅處理SharedViewController的附加協調器-這是很多開銷,並且在很大程度上違反了協調器的目的。

  2. SharedViewController實現FlowACoordinatableFlowBCoordinatable ...,並具有多個協調器屬性,並在適當的時間調用所有這些屬性。 還有很多開銷,樣板代碼和對協調員的調用。

關於如何解決這個問題的任何想法?

我也遇到同樣的情況,我也不知道最好的解決方案是什么。 我有一個必須在不同的協調器中使用的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
}

我確信這不是協議的最佳用法,希望遵循此線程的人能夠對此問題有更好的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM