|
// |
|
// Navigator.swift |
|
// tripani |
|
// |
|
// Created by Jesse Lin on 11/8/17. |
|
// Copyright © 2017 Tripani. All rights reserved. |
|
// |
|
|
|
import Foundation |
|
import UIKit |
|
import SafariServices |
|
import ESTabBarController_swift |
|
|
|
protocol Navigatable { |
|
var navigator: Navigator! { get set } |
|
} |
|
|
|
class Navigator { |
|
static var `default`: Navigator = { return Navigator() }() |
|
|
|
private lazy var tabBarController = TPTabBarController() |
|
|
|
// MARK: - segues list |
|
enum Scene { |
|
enum Transition { |
|
case root(in: UIWindow) |
|
case navigation, modal |
|
} |
|
|
|
// all app scenes |
|
case tabs |
|
|
|
//case profileTab(ProfilePagerType) |
|
|
|
case webPage(URL) |
|
} |
|
|
|
// MARK: - get a single VC |
|
func get(segue: Scene, storyboard: UIStoryboard) -> UIViewController { |
|
switch segue { |
|
|
|
case .tabs: |
|
return tabBarController |
|
|
|
// case .profileTab(let type): |
|
// let vm = ProfileInfoTabViewModel() |
|
// return ProfileInfoTabVC.createWith(R.storyboard.profile(), viewModel: vm, type: type) |
|
|
|
case .webPage(let url): |
|
let safari = SFSafariViewController(url: url) |
|
safari.hidesBottomBarWhenPushed = true |
|
return safari |
|
} |
|
} |
|
|
|
func show(segue: Scene, sender: UIViewController?, transition: Scene.Transition = .navigation) { |
|
let storyboard = sender?.storyboard ?? R.storyboard.main() |
|
let target = get(segue: segue, storyboard: storyboard) |
|
|
|
show(target: target, sender: sender, transition: transition) |
|
} |
|
|
|
// MARK: - Private Method |
|
|
|
private func show(target: UIViewController, sender: UIViewController?, transition: Scene.Transition) { |
|
injectNavigator(in: target) |
|
|
|
switch transition { |
|
case .root(in: let window): |
|
UIView.transition(with: window, duration: 0.5, options: .transitionFlipFromLeft, animations: { |
|
window.rootViewController = target |
|
}, completion: nil) |
|
return; |
|
default: break |
|
} |
|
|
|
guard let sender = sender else { |
|
fatalError("You need to pass in a sender for .navigation or .modal transitions") |
|
} |
|
|
|
if let nav = sender as? UINavigationController { |
|
//push root controller on navigation stack |
|
nav.pushViewController(target, animated: false) |
|
return |
|
} |
|
|
|
switch transition { |
|
case .navigation: |
|
if let nav = sender.navigationController { |
|
//add controller to navigation stack |
|
nav.pushViewController(target, animated: true) |
|
} |
|
case .modal: |
|
//present modally |
|
sender.present(target, animated: true, completion: nil) |
|
default: break |
|
} |
|
} |
|
|
|
private func injectNavigator(in target: UIViewController) { |
|
// view controller |
|
if var target = target as? Navigatable { |
|
target.navigator = self |
|
return |
|
} |
|
|
|
// tabs |
|
if let target = target as? UITabBarController, let children = target.viewControllers { |
|
for vc in children { |
|
injectNavigator(in: vc) |
|
} |
|
} |
|
|
|
// navigation controller |
|
if let target = target as? UINavigationController, let root = target.viewControllers.first { |
|
injectNavigator(in: root) |
|
} |
|
} |
|
} |