swift中如何基于协议实现路由

How to implement routing in swift based on protocols

我想像 ReactJS 一样在 Swift 中实现路由,我已经实现了用于路由的协议。

但它在 UIViewController 扩展中崩溃了。谁能帮我解决这个问题。

这是我的代码。

import Foundation
import UIKit

extension UIViewController {
    func presented(_ animated: Bool) {
        print("\(#function)")
        present(Route.destination, animated: animated,
                completion: nil)
    }

    func pushed(_ animated: Bool) {
        print("\(#function)")
        _ = navigationController?.pushViewController(Route.destination,
                                                     animated: true)
    }
}

protocol Router {
    static func toController <T: UIViewController>(_ controller:T,
                                                   params: Any) -> T
}

class Route : Router {
    static var destination: UIViewController!

    static func toController<T:UIViewController>(_ controller: T,
                                                 params: Any) -> T {
        let viewController : T = UIStoryboard(name: "Main", bundle: nil)
            .instantiateViewController(withIdentifier: String(describing: T.self)) as! T

        destination = viewController
        return viewController
    }
}



class ViewController: UIViewController {
     @IBAction func navigate() {
            Route.toController(SecondViewControlller(), params: [])
                .presented(true)
      }
}

The app is crashing because you are going to present the same viewController on itself.

原因是下面的方法将目标 viewController 作为参数并将 return 本身作为目标。

static func toController <T: UIViewController>(_ controller:T, params: Any) -> T

除此之外,每当从 Route.toController(SecondViewControlller(), params: []).presented(true) 调用 presented(_ animated: Bool) 时,selfRoute.destination 是相同的。因此,它会导致在自身上呈现相同的 viewController 并导致某种低于错误或使应用程序崩溃。

Attempt to present on whose view is not in the window hierarchy!

试试这个:

extension UIViewController {
    func presented(_ animated: Bool) {
        print("\(#function)")
        self.present(Route.destination, animated: animated, completion: nil)
    }

    func pushed(_ animated: Bool) {
        print("\(#function)")
        _ = self.navigationController?.pushViewController(Route.destination, animated: true)
    }
}

protocol Router {
    static func toController <T: UIViewController, T2: UIViewController>(_ controller: T2, from source: T, params: Any) -> T
}

class Route : Router {
    static var destination: UIViewController!

    static func toController <T: UIViewController, T2: UIViewController>(_ controller: T2, from source: T, params: Any) -> T {
        let viewController : T2 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: String(describing: T2.self)) as! T2

        destination = viewController
        return source
    }
}

//Your ViewController.swift
@IBAction func onButtonTap(_ sender: Any) {

    Route.toController(SecondViewControlller(), from: self, params: []).presented(true)
}