Skip to content

Instantly share code, notes, and snippets.

@damodarnamala
Created April 29, 2020 20:26
Show Gist options
  • Save damodarnamala/6d649f9ffae384c326386df68414cc61 to your computer and use it in GitHub Desktop.
Save damodarnamala/6d649f9ffae384c326386df68414cc61 to your computer and use it in GitHub Desktop.
import Foundation
import UIKit
public class Router {
static let window = UIApplication.shared
.connectedScenes
.filter({$0.activationState == .foregroundActive})
.map({$0 as? UIWindowScene})
.compactMap({$0})
.first?.windows
.filter({$0.isKeyWindow}).first
class var navigationController: UINavigationController {
guard let rootNavigationController = window?
.rootViewController as? UINavigationController else {
// Application window will not be created yet need to try after some time.
// returning a new instance of navigationcontroller as fall back
return UINavigationController()
}
return rootNavigationController
}
class func contais(_ viewController: AnyClass) -> Bool {
return self.navigationController
.viewControllers.contains { type(of: $0) == viewController }
}
class func viewController(type viewController: AnyClass) -> UIViewController? {
return self.navigationController
.viewControllers.first(where: { type(of: $0) == viewController })
}
class func push(to viewController: Scene, animated: Bool = true) {
let controller = Router.viewController(viewController)
self.navigationController.pushViewController(controller, animated: animated)
}
class func pop() {
self.navigationController.popViewController(animated: true)
}
class func popToRootViewController() {
self.navigationController.popToRootViewController(animated: true)
}
class func pop(to viewController: AnyClass) {
if let index = self.navigationController.viewControllers
.firstIndex(where: { type(of: $0) == viewController }) {
let viewController = self.navigationController.viewControllers[index]
self.navigationController.popToViewController(viewController, animated: true)
}
}
class func present(to viewController: Scene) {
let controller = Router.viewController(viewController)
self.navigationController.viewControllers.first?.present(controller, animated: true)
}
class func dismiss() {
self.navigationController.viewControllers.last?.dismiss(animated: true)
}
}
public protocol Navigation {}
enum Scene: Navigation {
case profile
case about
}
extension Router {
public static func viewController <T: UIViewController>(_ navigation: Navigation) -> T {
if let navigation = navigation as? Scene {
switch navigation {
case .profile:
// container.resolveViewController
return ProfileViewController.instance()
case .about: return AboutViewController.instance()
}
}
return UIViewController() as! T
}
}
extension UIStoryboard {
// MARK: - Storyboards
static var main: UIStoryboard {
return UIStoryboard.init(name: "Main", bundle: nil)
}
}
extension UIViewController {
static func instance<T: UIViewController>() -> T {
let name = String(describing: self)
guard let controller = UIStoryboard.main.instantiateViewController(withIdentifier: name) as? T else {
fatalError("ViewController '\(name)' is not of the expected class \(T.self).")
}
return controller
}
}
// Usage
1. To Push
Router.push(to: .profile)
2. To Pop
Router.pop()
3. To Present
Router.present(to: .about)
4. To Dismiss
Router.dismiss()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment