讀URLNavigator源碼

URLNavigator是Swift版本的Router。

Router的主要作用是解耦聚至。之前在各個ViewController間跳轉(zhuǎn),需要import ViewController爹梁,這樣就造成ViewController之間的依賴搀别,也即耦合。通過router不需要再import ViewController执赡。所有的只要import router镰踏,只依賴router這一個類,router里再去import 其他的ViewController沙合,這樣奠伪,就達(dá)到我們說的解耦。

一個基本完善的router首懈,我認(rèn)為應(yīng)該有下面幾個核心功能:

  • 跳轉(zhuǎn)ViewController
  • 跳轉(zhuǎn)服務(wù)
  • 回傳值

跳轉(zhuǎn)ViewController是基本功能绊率,這里包括跳轉(zhuǎn)的時(shí)候,傳入?yún)?shù)究履。

對于跳轉(zhuǎn)滤否,我們需要做到通過一個字符串,來跳轉(zhuǎn)到我們想要的頁面最仑,那么我們首先要做的是將字符串和對應(yīng)的頁面關(guān)聯(lián)起來藐俺,到時(shí)候炊甲,你給我這個字符串,我就知道你需要去哪個頁面欲芹。

URLNavigator里有一個注冊方法纤掸,就是將字符串和需要跳轉(zhuǎn)的ViewController關(guān)聯(lián)起來论咏。

navigator.register("navigator://user") { url, values, context in
      return UserViewController()
    }

更進(jìn)一步,可以在字符串里把需要傳遞的參數(shù)也帶上

navigator.register("navigator://user/<username>") { url, values, context in
      guard let username = values["username"] as? String else { return nil }
      return UserViewController(navigator: navigator, username: username)
    }

這樣不僅可以跳轉(zhuǎn)到關(guān)聯(lián)頁面,還能傳遞參數(shù)嫩码。
register里面做的事很簡單,就是用一個字典將字符串和和ViewController關(guān)聯(lián)起來亮靴。

public typealias URLPattern = String
private var viewControllerFactories = [URLPattern: ViewControllerFactory]()
open func register(_ pattern: URLPattern, _ factory: @escaping ViewControllerFactory) {
    self.viewControllerFactories[pattern] = factory
  }

將字符串作為字典的key缀磕,創(chuàng)建ViewController的閉包作為value,就這樣關(guān)聯(lián)了字符串和ViewController梆奈。

在調(diào)用的時(shí)候野崇,再根據(jù)字符串找到相應(yīng)的閉包,得到ViewController亩钟,執(zhí)行跳轉(zhuǎn)動作乓梨。

open func viewController(for url: URLConvertible, context: Any? = nil) -> UIViewController? {
    let urlPatterns = Array(self.viewControllerFactories.keys)
    guard let match = self.matcher.match(url, from: urlPatterns) else { return nil }
    guard let factory = self.viewControllerFactories[match.pattern] else { return nil }
    return factory(url, match.values, context)
  }

viewControllerFactories字典里拿到factory,再執(zhí)行factory(url, match.values, context)清酥。

這里的guard let match = self.matcher.match(url, from: urlPatterns) else { return nil }是拿到url里的參數(shù)扶镀,這里面參數(shù)的傳入有一個自己定義的規(guī)則。URLMatcher.swift就是專門處理字符串的拆分焰轻,拿到參數(shù)臭觉。

然后

navigator.push("navigator://user/zhangsan")
navigator.present("navigator://user/zhangsan")

調(diào)用服務(wù),有時(shí)候辱志,我們并不想跳到一個頁面蝠筑,僅僅是想調(diào)用某個類里面的某個函數(shù)。

navigator.register("navigator://user/<username>") { url, values, context in
      guard let username = values["username"] as? String else { return nil }
      return UserViewController(navigator: navigator, username: username)
    }

這個是上面的注冊代碼揩懒,我們只要修改一下就可以了什乙,調(diào)用服務(wù),其他的操作一樣

navigator.register("navigator://user/<username>") { url, values, context in
      guard let username = values["username"] as? String else { return nil }
      //獲取UserViewController對象 userVC已球,調(diào)用方法
        userVC.callFuc(username: username)
    }

這個是我假想的一個方法臣镣。實(shí)際有一個和register類似的方法

private var handlerFactories = [URLPattern: URLOpenHandlerFactory]()
open func handle(_ pattern: URLPattern, _ factory: @escaping URLOpenHandlerFactory) {
    self.handlerFactories[pattern] = factory
  }

有一個保存閉包和字符串對應(yīng)關(guān)系的字典handlerFactories,不和register字典共用和悦。
所以調(diào)用方法是

navigator.handle("navigator://user/<username>") { (url, values, context) -> Bool in
      guard let username = values["username"] as? String else { return nil }
      //獲取UserViewController對象 userVC退疫,調(diào)用方法
        userVC.callFuc(username: username)
      return true
    }

回傳值,有時(shí)候鸽素,我們跳轉(zhuǎn)到某個頁面褒繁,需要這個頁面執(zhí)行后,把相關(guān)結(jié)果返回馍忽。

目前棒坏,URLNavigator還沒有第三個功能燕差。

總結(jié)一下:自己定義一個字符串規(guī)則,包含頁面信息和參數(shù)信息坝冕,然后將字符串和對應(yīng)的閉包關(guān)聯(lián)起來徒探,閉包可以是創(chuàng)建相應(yīng)ViewController的操作,也可以是調(diào)用函數(shù)的操作喂窟,也可以是其他操作测暗。在router通過字符串跳轉(zhuǎn)的時(shí)候,拿到字符串磨澡,解析出參數(shù)碗啄,找到相應(yīng)的閉包,將參數(shù)傳給閉包執(zhí)行稳摄,執(zhí)行閉包得到的ViewController稚字,拿去跳轉(zhuǎn)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末厦酬,一起剝皮案震驚了整個濱河市胆描,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌仗阅,老刑警劉巖昌讲,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異减噪,居然都是意外死亡剧蚣,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門旋廷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人礼搁,你說我怎么就攤上這事饶碘。” “怎么了馒吴?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵扎运,是天一觀的道長。 經(jīng)常有香客問我饮戳,道長豪治,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任扯罐,我火速辦了婚禮负拟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘歹河。我一直安慰自己掩浙,他們只是感情好花吟,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著厨姚,像睡著了一般衅澈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谬墙,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天今布,我揣著相機(jī)與錄音,去河邊找鬼拭抬。 笑死部默,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的玖喘。 我是一名探鬼主播甩牺,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼累奈!你這毒婦竟也來了贬派?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤澎媒,失蹤者是張志新(化名)和其女友劉穎搞乏,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體戒努,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡请敦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了储玫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侍筛。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖撒穷,靈堂內(nèi)的尸體忽然破棺而出匣椰,到底是詐尸還是另有隱情,我是刑警寧澤端礼,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布禽笑,位于F島的核電站,受9級特大地震影響蛤奥,放射性物質(zhì)發(fā)生泄漏佳镜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一凡桥、第九天 我趴在偏房一處隱蔽的房頂上張望蟀伸。 院中可真熱鬧,春花似錦、人聲如沸望蜡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽脖律。三九已至谢肾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間小泉,已是汗流浹背芦疏。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留微姊,地道東北人酸茴。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像兢交,于是被迫代替她去往敵國和親薪捍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容