URLNavigator使用指南及擴展

來源:

URLNavigator是devxoul發(fā)布在github上的一個開源庫,他倉庫下面還包括了(Then, SwiftyImage, ReactorKit)等很有名的開源庫。

URLNavigator是什么:

devxoul 簡單的寫了一句話:Elegant URL Routing for Swift
其實就是優(yōu)雅的路由跳轉為了解耦模塊。

我們平時怎么做跳轉:

self.navigationController?.pushViewController(MineViewController(), animated: true)

這是我們平時的路由跳轉的方式,看上去沒什么不好的地方。其實我也覺得只要能完成項目都是好的,但是說句官方話:好處是移除 ViewController 中的依賴關系...

URLNavigator原理:

其實大多數(shù)的Router開源庫原理都差不多,1.解析URL。2.根據(jù)解析好的URL去跳轉,或是做其他的事情。

使用

使用起來也異常的簡單明了,首先pod...這就不說了。

Appdelegate.swift

private var navigator: NavigatorType?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
     let navigator = Navigator()
     NavigatorMap.initialize(navigator: navigator)
}

NavigatorMap.swift

navigator.register("navigator://mine/<mine>") { url , values, context in
    guard let userinfoString = values["mine"] as? String else { return nil }
    return MineViewController(navigator: navigator, userInfo: userinfoString.toObject(UserInfo.self))
}

當我要跳轉到MineViewController我應該怎么做呢?重點來了 ↓↓↓↓↓↓↓

navigator.push("navigator://mine/abc")
// abc是我要傳遞給第二個頁面的參數(shù)

好了,URLNavigator的主要功能已經(jīng)演示完畢了,下面我們來看一個問題。

如果我傳遞過去的參數(shù)不止一個我該怎么辦????
解答:URLNavigator提供的有path函數(shù)在(URLMatcher)的里面

但是!我想要傳一個模型對象過去該怎么辦???
我看了一下源碼還真的無法做到,平常比如說我們在A頁面然后我們有個UserInfo類,當我們跳轉到B頁面要帶UserInfo的實例過去,那我們用URLNavigator應該怎么做呢?

我的想法:吧UserInfo實例轉化成JSON格式的字符串然后拼接在"navigator://mine/{json格式的字符串}"就可以了吧。
實驗:發(fā)現(xiàn)確實可以
又一個想法:當我B頁面拿到這個JSON格式的字符串總要換成模型吧,當然Decoable能幫我們解決,可是我們畢竟是為了解耦,swift又這么方便,如果我們有UserInfo實例,又有Dog實例,Person, User, Model等等都需要轉換,我們怎么樣寫一個函數(shù)就把所有的都實現(xiàn)呢?
實驗:泛型

<不要問我怎么不傳字典,本文只針對模型>

擴展:

OK,現(xiàn)在我們回到上面的第一個問題,怎么把一個model轉換為JSON格式的字符串.

  1. model遵守Codable協(xié)議
  2. 用JSONEncoder進行解析
定義ConvertToStringable協(xié)議
protocol ConvertToStringable {
    associatedtype Result: Codable
    var valueString: String { get }
}

extension ConvertToStringable {
    func toString(result: Result) -> String {
        let data = try? JSONEncoder().encode(result)
        guard let da = data else { return "" }
        guard let st = String.init(data: da, encoding: .utf8) else { return "" }
        return st
    }
}

我們使用關聯(lián)類型來匹配不同的模型實例,然后我們在每個需要model轉為JSON格式字符串的model里擴展一下model:

struct UserInfo: Codable {
    var name: String
    var age: Int
    var avator: String
}

extension UserInfo: ConvertToStringable {
    typealias Result = UserInfo
    var valueString: String { return toString(result: self) }
}

OK! 這下可以了我們來做個試驗:

let userinfo = UserInfo(name: "Hally", age: 2, avator: "333")
userinfo.valueString
//打印:navigator://mine/{"name":"Hally","age":2,"avator":"333"}

哦喲還不錯哦。
這個問題算是解決了,并且也用到了很swifty的方式,下面到第二個問題了,我們怎么在B頁面把傳遞過來的JSON格式字符串反推回model -> 泛型
怎么做?

// 因為JSON格式的字符串就是一個字符串,所以我們只要擴展一下String就OK啦。
extension String {
    func toObject<T>(_ : T.Type) -> T? where T: Codable {
        guard let data = self.data(using: .utf8) else { return nil }
        return try? JSONDecoder().decode(T.self, from: data)
    }
}

然后怎么使用嘞?

// 其實上面我已經(jīng)使用過了(NavigatorMap)類里
// userinfoString = "{\"name\":\"Hally\",\"age\":2,\"avator\":\"333\"}"
let userInfo = userinfoString.toObject(UserInfo.self)
// 最后得到userInfo的實例對象

最后我們就可以在B頁面愉快的使用userInfo了,這樣傳遞模型的擴展就完成了。僅供小白參考,大神請狠狠的指教。
UseageURLNavigator 代碼地址

感謝@故事的小黃瓜提供的泛型思路

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

相關閱讀更多精彩內容

  • 發(fā)現(xiàn) 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 15,654評論 4 61
  • 小A是我現(xiàn)在公司共事了兩個月的同事。半個月前,他被公司離職了。 他是一個為人比較誠懇的人,講起普通話的...
    王糊糊閱讀 427評論 0 1
  • 因為有你們的存在,我的生活更加精彩,不會用太多華麗的語言去形容,但是有了你們才像是擁有一個大家庭 劉旭東同學: 雖...
    小可愛_df3f閱讀 787評論 2 2
  • 原創(chuàng) 2017-10-30 更多資訊 思齊俱樂部 專欄作者/Chenlia 一個醫(yī)藥行業(yè)的小學生。 案例說丨背景:...
    鳳凰涅磐0閱讀 644評論 0 0
  • 姓名:李淑瑛 224期學員 289期志工 325期志工 公司:紹興翔鷹紡織品有限公司 部門:人事行政部 【堅持日精...
    李淑瑛閱讀 152評論 0 0

友情鏈接更多精彩內容