阅读 228

Swift-Router 自己写个路由吧,第三方总是太复杂

先看看这个路由的使用吧
  1. 如果是网络地址,会直接自动跳转到 OtherWKWebViewController

  2. 如果是应用内部的手动调用跳转

  • 直接跳转视图控制器

    • EPRouter.pushViewController(EPSMSLoginViewController())

  • 先在 RouteDict 注册映射关系再跳转

    • EPRouter.pushAppURLPath("goods/detail?spellId=xxx&productId=xxx")

  1. 又服务器来控制跳转 也得在 RouteDict 注册映射关系,只不过多加了一个 scheme

    • EPRouter.pushURLPath("applicationScheme://goods/detail?spellId=xxx&productId=xxx")

**!!!支持Swift、OC、Storyboard的跳转方式,可以在 loadViewController 看到实现方式 **

EPRouter的全部代码
class EPRouter: NSObject {     private static let RouteDict:[String:String] = [         "order/list"            :"OrderListPageViewController",   // 订单列表 segmentIndex         "order/detail"          :"OrderDetailViewController",     // 订单详情 orderId         "goods/detail"          :"GoodsDetailViewController",     // 商品详情productId         "goods/list"            :"GoodsCategoryViewController",   // type brandId 跳转到某个分类;跳转到某个品牌         "goods/search"          :"SearchListViewController",      // 搜索商品 text         "coupon/list"           :"CouponListViewController",      // 优惠券列表         "cart/list"             :"CartViewController",            // 购物车列表         "address/list"          :"AddressListViewController",     // 收货地址列表     ]           // 返回首页,然后指定选中模块 public static func backToTabBarController(index: NSInteger, completion:(()->())?=nil) {     guard let vc = EPCtrlManager.getTopVC(), let nav = vc.navigationController, let tabBarCtrl = nav.tabBarController  else {         return     }     nav.popToRootViewController(animated: false)     DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+0.1) {         tabBarCtrl.selectedIndex = index         completion?()     } } // 销毁n个界面 不建议使用这个方法 可以在pushAppURLPath方法中设置destroyTime达到一样的效果,又可以避免用户侧滑返回 public static func popViewController(animated: Bool, time:NSInteger=1) {     guard let nav = EPCtrlManager.getTopVC()?.navigationController else {         return     }     let vcs = nav.viewControllers     let count = vcs.count     let index = (count - 1) - time     if index >= 0 {         let vc = vcs[index]         nav.popToViewController(vc, animated: true)     } else {         nav.popViewController(animated: true)     } }     /// 回到目标控制器     public static func popViewController(targetVC: UIViewController.Type, animated: Bool, toRootVC: Bool=true) {         popViewController(targetVCs: [targetVC], animated: animated, toRootVC: toRootVC)     }          /// 回到目标控制器[vc],从前到后 没有目标控制器是否回到根视图     public static func popViewController(targetVCs: [UIViewController.Type], animated: Bool, toRootVC: Bool=true) {         guard let nav = EPCtrlManager.getTopVC()?.navigationController else {             return         }         let vcs = nav.viewControllers         var canPop = false         for vc in vcs {             for tvc in targetVCs {                 if vc.isMember(of: tvc) {                     canPop = true                     nav.popToViewController(vc, animated: animated)                     break                 }             }         }         if !canPop && toRootVC {             nav.popToRootViewController(animated: animated)         }     }     /// push 一个vc --- destroyTime: push之前要销毁的几个压栈vc     @objc public static func pushAppURLPath(_ path: String, query: [AnyHashable: Any]=[:], animated: Bool=true, destroyTime:NSInteger=0) {         var urlString = "applicationScheme://"+path         if path.contains("http://") || path.contains("https://") {             urlString = path         }         pushURLString(urlString, query: query, animated: animated, destroyTime: destroyTime)     }     @objc public static func pushURLString(_ urlString: String, query: [AnyHashable: Any]=[:], animated: Bool=true, destroyTime:NSInteger=0) {         guard let tvc = loadViewControllerWitURI(urlString, query: query) else {             return         }         pushViewController(tvc, animated: animated, destroyTime: destroyTime)     }     @objc public static func pushViewController(_ tvc: UIViewController, query: [AnyHashable: Any]=[:], animated: Bool=true, destroyTime:NSInteger=0) {         guard let vc = EPCtrlManager.getTopVC() else {             return         }         if let _ = tvc.pushInfo {             tvc.pushInfo?.merge(query, uniquingKeysWith: { (_, new) in new })         }else {             tvc.pushInfo = query         }         guard let nav = vc.navigationController else {             vc.present(tvc, animated: true, completion: nil)             return         }         tvc.hidesBottomBarWhenPushed = true         if destroyTime > 0 {             let vcs = nav.viewControllers             let count = vcs.count             var index = (count - 1) - destroyTime             if index < 0 { // destroyTime 很多时,直接从根视图push                 index = 0             }             var reVCS = [UIViewController]()             for vc in nav.viewControllers[0...index] {                 reVCS.append(vc)             }             reVCS.append(tvc)             nav.setViewControllers(reVCS, animated: animated)         }else {             nav.pushViewController(tvc, animated: animated)         }     }     public static func loadViewController(_ className: String, parameters: [AnyHashable: Any]? = nil) -> UIViewController? {         var desVC: UIViewController?         let spaceName = (Bundle.main.infoDictionary?["CFBundleExecutable"] as? String) ?? "ApplicationName"         if let vc = storyboardClass(className) { // storyboard             desVC = vc         }else if let aClass = NSClassFromString("\(spaceName).\(className)") { // Swift             if aClass is UIViewController.Type {                 let type = aClass as! UIViewController.Type                 desVC = type.init()             }         }else if let aClass = NSClassFromString("\(className)") { // OC             if aClass is UIViewController.Type {                 let type = aClass as! UIViewController.Type                 desVC = type.init()             }         }         desVC?.pushInfo = parameters         return desVC     }     public static func loadViewController(_ viewController: UIViewController, parameters: [AnyHashable: Any]? = nil) -> UIViewController {         viewController.pushInfo = parameters         return viewController     }     public static func loadViewControllerWitURI(_ urlString: String, query: [AnyHashable: Any]? = nil) -> UIViewController? {                  // 先进行编码,防止有中文的带入, 不行进行二次编码         var urlString = urlString         if (URLComponents(string: urlString) == nil) {             urlString = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? urlString         }         guard let url = URLComponents(string: urlString), let scheme = url.scheme else {             HGLog("无效的地址:\(urlString)")             return nil         }         if scheme == "http" || scheme == "https" {             let webVC = OtherWKWebViewController()             webVC._urlStr = urlString             return webVC         } else if String(format: "%@://", scheme) == "appcationScheme://" {             let path = (url.host ?? "") + url.path             guard  var vcClassName = RouteDict[path] else {                 HGLog("没有配置视图控制器呢。。。:\(urlString)")                 return nil             }             var info: [AnyHashable: Any]?             if query?.count ?? 0 > 0 {                 info = [AnyHashable: Any]()                 for (key, value) in query! {                     info![key] = value                 }             }             if let queryItems = url.queryItems {                 if info == nil {                     info = [AnyHashable: Any]()                 }                 for item in queryItems {                     if let value = item.value {                         info![item.name] = value                     }                 }             }             return loadViewController(vcClassName, parameters: info)         }         HGLog("未知scheme:\(urlString)")         return nil     }          private static func storyboardClass(_ className: String) -> UIViewController? {         if className == "VIPWithdrawViewController" { // 提现             let vc = UIStoryboard.init(name: "VIP", bundle: nil).instantiateViewController(withIdentifier: "withdrawTVC")             return vc         }else if className == "VIPRecordListViewController" { // 提现记录             let vc = UIStoryboard.init(name: "VIP", bundle: nil).instantiateViewController(withIdentifier: "recordListVC")             return vc         }         return nil     } } 复制代码

用来跳转传递数据的扩展属性
extension UIViewController {     private struct PushAssociatedKeys {         static var pushInfo = "pushInfo"     }     @objc open var pushInfo: [AnyHashable: Any]? {         get {             return objc_getAssociatedObject(self, &PushAssociatedKeys.pushInfo) as? [AnyHashable : Any]         }         set(newValue) {             objc_setAssociatedObject(self, &PushAssociatedKeys.pushInfo, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)         }     } } 复制代码

可见视图控制器的获取
class EPCtrlManager: NSObject {     public static let `default`: EPCtrlManager = {         return EPCtrlManager()     }()     // MARK: **- 查找顶层控制器、**     // 获取顶层控制器 根据window     @objc public static func  getTopVC() -> UIViewController? {         var window = UIApplication.shared.keyWindow         //是否为当前显示的window         if window?.windowLevel != UIWindow.Level.normal{             let windows = UIApplication.shared.windows             for  windowTemp in windows{                 if windowTemp.windowLevel == UIWindow.Level.normal{                     window = windowTemp                     break                 }             }         }         let vc = window?.rootViewController         return getTopVC(withCurrentVC: vc)     }     ///根据控制器获取 顶层控制器     private static func  getTopVC(withCurrentVC VC :UIViewController?) -> UIViewController? {         if VC == nil {             print("????: 找不到顶层控制器")             return nil         }         if let presentVC = VC?.presentedViewController {             //modal出来的 控制器             return getTopVC(withCurrentVC: presentVC)         }else if let tabVC = VC as? UITabBarController {             // tabBar 的跟控制器             if let selectVC = tabVC.selectedViewController {                 return getTopVC(withCurrentVC: selectVC)             }             return nil         } else if let naiVC = VC as? UINavigationController {             // 控制器是 nav             return getTopVC(withCurrentVC:naiVC.visibleViewController)         } else {             // 返回顶控制器             return VC         }     } }


作者:TralyFang
链接:https://juejin.cn/post/7002427993792446501


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐