簡體   English   中英

Swift:如何使用 Xcoordinator 從子協調器設置根視圖 controller?

[英]Swift: How to use Xcoordinator to set a root view controller from child coordinator?

我試圖了解如何使用 XCoordinator 從子協調員那里設置根視圖 controller。

我有一個運行應用程序協調器的應用程序委托。

我的模式是:

AppDelegate - 應用協調器 --- 主菜單協調器 --- 游戲協調器

(見圖)

協調器圖

應用程序協調器不應該直接了解特定的視圖控制器,因為我認為視圖控制器應該由它們各自的協調器管理。

因此,應用程序協調器應該管理協調器之間的流程並設置一個根初始協調器。

可悲的是,屏幕是空白的,並且一直抱怨我不能“不支持推送導航 controller”。

但是,如果我直接在我的 appcoordinator 中實例化視圖 controller 就很好,我不知道為什么。

// AppCoordinator
enum AppRoute: Route {
    case mainmenu
    case game
}

class AppCoordinator: NavigationCoordinator<AppRoute> {

    init() {
        super.init(initialRoute: .mainmenu)
    }

    // MARK: Overrides
    override func prepareTransition(for route: AppRoute) -> NavigationTransition {
        let router = MainMenuCoordinator().strongRouter
        return .push(router)
    }
}

這應該會啟動 MainMenuCoordinator 的初始視圖 controller

enum MainMenuRoute: Route {
    case mainmenu
}

// MainMenuCoordinator
class MainMenuCoordinator: NavigationCoordinator<MainMenuRoute> {

    init() {
        super.init(initialRoute: .mainmenu)
    }


    override func prepareTransition(for route: MainMenuRoute) -> NavigationTransition {
        print ("route: \(route as Any)")

            let vc = MainMenuViewController.instantiate(.main)
            return .push(vc)
     }
}

但這會返回一個空白屏幕,並抱怨不支持推送。

但是,如果我移動這段代碼:

let vc = MainMenuViewController.instantiate(.main)
return .push(vc)

到 AppCoordinator

像這樣:

// MARK: AppCoordinator Overrides
override func prepareTransition(for route: AppRoute) -> NavigationTransition {
    let vc = MainMenuViewController.instantiate(.main)
    return .push(vc)
}

沒關系。 出現了一個屏幕——但主菜單協調器不再被“關注”

我想知道 - 你是如何做到的,以便應用程序協調員將責任委托給它的子協調員?

感謝您提供的任何幫助。 謝謝


// 編輯:根據提供的答案,我嘗試了另一次嘗試,將父協調器的引用傳遞給子協調器。

我希望mainmenucoordinator使用它自己的路由集合; 我不想僅僅依賴AppRoutes中定義的任何路由。

所以我的應用協調員有這些路線:

enum AppRoute: Route {
    case mainmenu
    case game
}

class AppCoordinator: NavigationCoordinator<AppRoute> {

init() {
    let defaultRoute: AppRoute = .mainmenu
    super.init(initialRoute: defaultRoute)
    self.rootViewController.view.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
}

}

我的主要協調員有以下路線:

enum MainMenuRoute: Route {
    case mainmenu
    case selectPlayer
    case playgame
}

class MainMenuCoordinator: NavigationCoordinator<MainMenuRoute> {

    // For my child coordinators, keep a strong reference to parent
    private var router: StrongRouter<AppRoute>?
/// ...
}

當我開始初始化它時,我設置了父級。

// MainMenuCoordinator: Init
  convenience init(router: StrongRouter<AppRoute>) {
        self.init(initialRoute: .mainmenu)
    }

但現在它不會使用我為MainMenuCoordinator定義的任何路由; 相反,它使用AppRoute

例子:

嘗試在MainMenuCoordinator.prepareTransition中設置路由器

override func prepareTransition(for route: MainMenuRoute) -> NavigationTransition {
        print ("route: \(route as Any)")

        switch route {
        case .mainmenu:
            let vc = MainMenuViewController.instantiate(.main)
            vc.router = strongRouter
            return .push(vc)
        // ....
      }
}

主菜單視圖 controller 包含對以下內容的引用:

class MainMenuViewController: UIViewController, Storyboarded {

    // MARK: - Stored properties
    var router: UnownedRouter<MainMenuRoute>!
}

通過這些編輯,根視圖 controller 現在是白色的; 但記錄器仍然抱怨我無法推送視圖控制器。

我正在這樣做:

class MainCoordinator: NavigationCoordinator<ApplicationRoute> {

    convenience init() {
        var defaultRoute: ApplicationRoute = .showAuthentification
        if ApplicationSettings.shared.isLoggedIn {
            defaultRoute = .showApplicationRoot
        }

        self.init(defaultRoute: defaultRoute)
        self.rootViewController.view.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
    }

    override func prepareTransition(for route: ApplicationRoute) -> NavigationTransition {
        switch route {
            case .showAuthentification:
                return .multiple(.dismissToRoot(animation: .fadeInstant),
                                 .presentFullScreen(AuthentificationCoordinator(router: strongRouter),
                                                    animation: .fadeInstant))

            case .showApplicationRoot:
                return .multiple(.dismissToRoot(animation: .fadeInstant),
                                 .presentFullScreen(TabControllerCoordinator(router: strongRouter),
                                                    animation: .fadeInstant))

        }
    }
}

在獨生子女協調員中:

class AuthentificationCoordinator: NavigationCoordinator<AuthentificationRoute> {
    // For my child coordinators I keep a strong reference to the parent, so I can use it later
    private var router: StrongRouter<SMCApplicationRoute>?

    convenience init(router: StrongRouter<SMCApplicationRoute>) {
        self.init(defaultRoute: .initial)
        self.router = router
    }

    override func prepareTransition(for route: AuthentificationRoute) -> NavigationTransition {
        switch route {
        case .initial:
            let initialVC = LandingPageViewController.loadFromXIB(type: LandingPageViewController.self)
            initialVC.router = strongRouter
            return .push(initialVC, animation: .fade)

        case .showLogin:
            let loginVC = LoginViewController.loadFromXIB(type: LoginViewController.self)
            loginVC.router = strongRouter
            return .push(loginVC, animation: .fade)

        case .showHome:
            // Here I trigger the other route from MainCoordinator. If I log in, the AuthentificationCoordinator will get destroyed, with all the child coordinators with root controllers
            return .trigger(SMCApplicationRoute.showApplicationRoot, on: router!)
        }
    }
}

我認為有更好的解決方案,但我發現這是有效的。 如果代碼不能自我解釋,請告訴我;)

暫無
暫無

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

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