219 lines
7.6 KiB
Swift
219 lines
7.6 KiB
Swift
//
|
|
// AppRouter.swift
|
|
// Alamofire
|
|
//
|
|
// Created by osell on 2023/2/7.
|
|
//
|
|
|
|
import Foundation
|
|
import URLNavigator
|
|
|
|
public typealias RouterParameter = [String : Any]
|
|
public typealias CustomHandlerFactory = (String, RouterParameter?) -> Bool
|
|
public typealias ContextHander = (String, RouterParameter) -> UIViewController?
|
|
|
|
public protocol AppRouterProtocol: CustomStringConvertible {
|
|
func setupRegisterRouter()
|
|
func setupHandlerRouter()
|
|
}
|
|
|
|
@objcMembers
|
|
public class AppRouter: NSObject {
|
|
|
|
public static let shared = AppRouter()
|
|
|
|
private let navigator: Navigator
|
|
|
|
static var globalRouteHandler: CustomHandlerFactory?
|
|
|
|
var rootViewController: UIViewController? {
|
|
return UIViewController.topMost
|
|
}
|
|
|
|
var navigationController: UINavigationController? {
|
|
return UIViewController.topMost?.navigationController
|
|
}
|
|
|
|
override init() {
|
|
self.navigator = Navigator()
|
|
super.init()
|
|
}
|
|
|
|
public func setup() {
|
|
if let this = self as? AppRouterProtocol {
|
|
this.setupRegisterRouter()
|
|
this.setupHandlerRouter()
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Register/Handler
|
|
public extension AppRouter {
|
|
|
|
/// 注册路由
|
|
/// - Parameters:
|
|
/// - router: 路由
|
|
/// - factory: ViewControllerFactory
|
|
class func register(_ router: RouterTarget, factory: @escaping ContextHander) {
|
|
AppRouter.shared.navigator.register(router.url) { _, values, context in
|
|
var values = values
|
|
if let userInfo = context as? RouterParameter {
|
|
values.merge(userInfo, uniquingKeysWith: { value1, value2 in value2 })
|
|
}
|
|
return factory(router.url, values)
|
|
}
|
|
}
|
|
|
|
/// 处理单个路由
|
|
/// - Parameters:
|
|
/// - router: 路由
|
|
/// - factory: URLOpenHandlerFactory
|
|
class func handle(_ router: RouterTarget, _ factory: @escaping CustomHandlerFactory) {
|
|
AppRouter.shared.navigator.handle(router.url) { _, values, context in
|
|
var values = values
|
|
if let userInfo = context as? RouterParameter {
|
|
values.merge(userInfo, uniquingKeysWith: { value1, value2 in value2 })
|
|
}
|
|
return factory(router.url, values)
|
|
}
|
|
}
|
|
|
|
/// 处理全局路由设置
|
|
/// - Parameter handler: CustomHandlerFactory
|
|
class func globalRouteHandler(_ handler: CustomHandlerFactory?) {
|
|
AppRouter.globalRouteHandler = handler
|
|
}
|
|
|
|
/// 是否注册过路由
|
|
/// - Parameter url: 路由url
|
|
/// - Returns: true/false
|
|
class func isRegisterRouter(_ url: String, userInfo: RouterParameter?) -> Bool {
|
|
AppRouter.viewController(url, userInfo: userInfo) != nil
|
|
}
|
|
|
|
class func viewController(_ url: String, userInfo: RouterParameter?) -> UIViewController? {
|
|
AppRouter.shared.navigator.viewController(for: url, context: userInfo)
|
|
}
|
|
}
|
|
|
|
// MARK: - Push/Present
|
|
public extension AppRouter {
|
|
|
|
/// Router RouteTarget Push
|
|
/// - Parameters:
|
|
/// - router: RouterTarget
|
|
/// - isHandler: 是否处理
|
|
/// - userInfo: 参数
|
|
/// - Returns: UIViewController
|
|
@discardableResult
|
|
class func push(_ router: RouterTarget,
|
|
userInfo: RouterParameter? = nil) -> UIViewController? {
|
|
var params = RouterParameter()
|
|
if let parameters = userInfo {
|
|
params = params.merging(parameters) { _, value2 in value2 }
|
|
}
|
|
guard AppRouter.globalRouteHandler?(router.url, params) == true else {
|
|
return nil
|
|
}
|
|
return AppRouter.shared.navigator.push(router.url, context: params)
|
|
}
|
|
|
|
/// Router URLString Push
|
|
/// - Parameters:
|
|
/// - router: URL String
|
|
/// - isHandler: 是否处理
|
|
/// - userInfo: 参数
|
|
/// - Returns: UIViewController
|
|
@discardableResult
|
|
class func push(_ url: String,
|
|
userInfo: RouterParameter? = nil) -> UIViewController? {
|
|
let url = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
|
|
guard let urlURL = URL(string: url) else { return nil }
|
|
var params = urlURL.queryParameters as RouterParameter
|
|
if let parameters = userInfo {
|
|
params = params.merging(parameters) { _, value2 in value2 }
|
|
}
|
|
guard AppRouter.globalRouteHandler?(url, params) == true else {
|
|
return nil
|
|
}
|
|
return AppRouter.shared.navigator.push(url, context: params)
|
|
}
|
|
|
|
/// Pushes the view controller to the navigation controller stack.
|
|
///
|
|
/// - note: It is not a good idea to use this method directly because this method requires all
|
|
/// parameters. This method eventually gets called when pushing a view controller, so
|
|
/// it's recommended to implement this method only for mocking.
|
|
@discardableResult
|
|
class func push(_ viewController: UIViewController, from: UINavigationControllerType? = nil, animated: Bool = true) -> UIViewController? {
|
|
return AppRouter.shared.navigator.push(viewController, from: from, animated: animated)
|
|
}
|
|
|
|
/// Router RouteTarget Present
|
|
/// - Parameters:
|
|
/// - router: RouterTarget
|
|
/// - isHandler: 是否处理
|
|
/// - userInfo: 参数
|
|
/// - Returns: UIViewController
|
|
@discardableResult
|
|
class func present(_ router: RouterTarget,
|
|
userInfo: RouterParameter? = nil,
|
|
completion: (() -> Void)? = nil) -> UIViewController? {
|
|
|
|
var params = RouterParameter()
|
|
if let parameters = userInfo {
|
|
params = params.merging(parameters) { _, value2 in value2 }
|
|
}
|
|
guard AppRouter.globalRouteHandler?(router.url, params) == true else {
|
|
return nil
|
|
}
|
|
return AppRouter.shared.navigator.present(router.url, context: params, completion: completion)
|
|
}
|
|
|
|
/// Router URLString Present
|
|
/// - Parameters:
|
|
/// - router: URL String
|
|
/// - isHandler: 是否处理
|
|
/// - userInfo: 参数
|
|
/// - Returns: UIViewController
|
|
@discardableResult
|
|
class func present(_ url: String,
|
|
userInfo: RouterParameter? = nil,
|
|
completion: (() -> Void)? = nil) -> UIViewController? {
|
|
let url = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
|
|
guard let urlURL = URL(string: url) else { return nil }
|
|
var params = urlURL.queryParameters as RouterParameter
|
|
if let parameters = userInfo {
|
|
params = params.merging(parameters) { _, value2 in value2 }
|
|
}
|
|
guard AppRouter.globalRouteHandler?(url, params) == true else {
|
|
return nil
|
|
}
|
|
return AppRouter.shared.navigator.present(url, context: params, completion: completion)
|
|
}
|
|
|
|
/// Router URLString Present
|
|
/// - Parameters:
|
|
/// - viewController: viewController
|
|
/// - animated:
|
|
/// - completion:
|
|
/// - Returns: UIViewController
|
|
@discardableResult
|
|
class func present(_ viewController: UIViewController, animated: Bool = true, completion: (() -> Void)? = nil) -> UIViewController? {
|
|
return AppRouter.shared.navigator.present(viewController, animated: animated, completion: completion)
|
|
}
|
|
|
|
func popOrDismiss() {
|
|
if navigationController?.viewControllers.count == 1 &&
|
|
navigationController?.presentingViewController != nil {
|
|
navigationController?.dismiss(animated: true, completion: nil)
|
|
} else {
|
|
navigationController?.popViewController(animated: true)
|
|
}
|
|
}
|
|
|
|
func popToRoot() {
|
|
navigationController?.popToRootViewController(animated: true)
|
|
}
|
|
}
|