Swift Router 頁(yè)面跳轉(zhuǎn)路由,組件解耦

Router

為什么要用到Router去做跳轉(zhuǎn):解耦、方便

像底下這種代碼可能寫(xiě)了很多很多遍了,尤其是在項(xiàng)目中某個(gè)頁(yè)面入口很多的情況下。

let xx = XX()

...

let vc = XXXViewController(xx:xxx)
self.navigationController?.pushViewController(vc, animated: true)

尤其是公司要開(kāi)發(fā)多個(gè)項(xiàng)目,對(duì)模塊進(jìn)行了拆分,組件化的模式需要中間一個(gè)Router去決定跳轉(zhuǎn)到那個(gè)模塊的頁(yè)面,而不是在每個(gè)頁(yè)面都import XX 耦合非常嚴(yán)重。

瀏覽了下GitHub上的兩個(gè)庫(kù),都不是很滿意

  • Router 比較Swifty,但是耦合比較嚴(yán)重,實(shí)現(xiàn)了很多暫時(shí)不需要的功能,每個(gè)VC需要將自己當(dāng)成字符串告訴Router , 還要告訴當(dāng)前的navigation , 使用了NSClassFromString根據(jù)字符創(chuàng)建的 AnyClass 。比較繁瑣-- 但是還有很好的思想可以借鑒的
  • FNUrlRoute 通過(guò)url形式跳轉(zhuǎn),看起來(lái)挺不錯(cuò),仔細(xì)看下代碼,首先AppDelegate要先用字符串和VC進(jìn)行映射,每個(gè)VC要傳入[String:AnyObject]? 進(jìn)行初始化,這個(gè)把VC的創(chuàng)建都限制死了。絕對(duì)用不了呀,還有那么多人star ...

說(shuō)完他們的不足,首先來(lái)看下我們這個(gè)Router設(shè)計(jì)要求

  • 解耦:調(diào)用者不知道VC的名字
  • 不要用字符串,字符串容易出錯(cuò)
  • 不能限制初始化方法
  • 調(diào)用者應(yīng)該非常簡(jiǎn)潔

那么不使用字符串很容易想到就是用枚舉來(lái)替代,枚舉中也可能映射VC呀,而且不用在AppDelegate中注冊(cè),不能限制初始化方法我們就用params字典去映射 Router 里面的方式 感覺(jué)比較好 , 自己肯定是知道自己怎么初始化的, 用協(xié)議的方式比用強(qiáng)迫字典初始化好很多

public typealias  RouterParameter = [String: Any]
public protocol Routable {
  /**
   類(lèi)的初始化方法
   - params 傳參字典
   */
  static func initWithParams(params: RouterParameter?) -> UIViewController
}

我們跳轉(zhuǎn)只需要知道哪個(gè)VC要傳的參數(shù),這個(gè)都交給枚舉就可以了,為了項(xiàng)目路徑映射和跳轉(zhuǎn)解耦,用一個(gè)協(xié)議

public protocol RouterPathable {
  var any: AnyClass { get }
  var params: RouterParameter? { get }
}

其他就交給跳轉(zhuǎn)了

open class func open(_ path:RouterPathable , present: Bool = false , animated: Bool = true , presentComplete: (()->Void)? = nil){
    if let cls = path.any as? Routable.Type {
      let vc = cls.initWithParams(params: path.params)
      vc.hidesBottomBarWhenPushed = true
      let topViewController = RouterUtils.currentTopViewController()
      if topViewController?.navigationController != nil && !present {
        topViewController?.navigationController?.pushViewController(vc, animated: animated)
      }else{
        topViewController?.present(vc, animated: animated , completion: presentComplete)
      }
    }
  }

其中有用到一個(gè)工具方法是獲取最上層的vc好進(jìn)行跳轉(zhuǎn),具體代碼可以去GitHub下載

使用: 需要使用router進(jìn)行跳轉(zhuǎn)的都要事先Routable 接口,調(diào)用者不需要

無(wú)參數(shù)

class AVC: UIViewController, Routable{
  override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = UIColor.red
  }

  static func initWithParams(params: RouterParameter?) -> UIViewController {
    return AVC()
  }
}

有參數(shù)


struct Demo {
  var name: String
  var id: Int
}

class RVC: UIViewController {
  let demo:Demo
  init(demo:Demo) {
    self.demo = demo
    super.init(nibName: nil, bundle: nil)
  }
  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
  
  override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = UIColor.white
    navigationItem.title = demo.name
  }
}

extension RVC: Routable {
  static func initWithParams(params: RouterParameter?) -> UIViewController {
    guard let demo = params?["demo"] as? Demo else {
      fatalError("params is wrong")
    }
    let rvc = RVC(demo: demo)
    return rvc
  }
}

路徑映射:

比如上面的vc都是其他模塊的,那么只有這個(gè)映射的枚舉需要引入其他模塊,調(diào)用者不需要 , 下面展示三個(gè)vc的路徑映射

enum RouterPath: RouterPathable {
  case avc
  case bvc(String)
  case rvc(Demo)
  
  var any: AnyClass {
    switch self {
    case .avc:
      return AVC.self
    case .bvc:
      return BVC.self
    case .rvc:
      return RVC.self
    }
  }
  
  var params: RouterParameter? {
    switch self {
    case .bvc(let name):
      return ["name":name]
    case .rvc(let demo):
      return ["demo":demo]
    default:
      return nil
    }
  }
}

只要實(shí)現(xiàn) RouterPathable 都可以 ,如果需要映射的vc特別多 , 也可以分組管理。

調(diào)用者就很方便了

Router.open(RouterPath.avc)
let demo = Demo(name: "RVC title", id: 1)
Router.open(RouterPath.rvc(demo))

或者present

Router.open(RouterPath.bvc("BVC title"), present: true)

項(xiàng)目地址: SwiftyRouter

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容