日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

另辟蹊径--极简Swifty路由

發布時間:2023/12/18 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 另辟蹊径--极简Swifty路由 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

另辟蹊徑--極簡Swifty路由

1. 前言

在組件化通信方案的設計之初,盡管我們是純Swift的組件化,我也一直難逃窠臼的想用注冊(無論是注冊協議還是注冊URL)的方式來解決問題,或者采用CTMediator的Target-Action方式,具體幾種組件化方案的實現與利弊見文章:iOS 組件化 —— 路由設計思路分析??

2. 彎路(經驗)

最開始設計的組件化解決方案,因為作為一個電商項目(才不是這個原因),所以我僅采用了URL注冊的方式,我一直力求的它應該具備的特性如下:

  • 組件解耦
  • 可以方便的跳轉到任何已注冊的頁面
  • 不要硬編碼
  • 模塊(組件)可獲取App生命周期
  • 模塊(組件)對URL的注冊不需要手動調用
  • 可能的話,實現3端一樣的跳轉邏輯
  • 支持動態下發,如此即支持簡單的熱修復
  • 其實3、4,已經跳出了組件路由設計的范疇。確切的說應該是模塊解耦的范疇。

    2.1 實現

    我把router設計成單例,目的是保證其持有的["String": func]的字典的唯一確定性,其中func作為閉包形式,傳入參數返回ViewController。那么注冊環節就顯而易見的為register(_ key: String, value: func),調用就會根據key,執行閉包func返回ViewController,以此解決1。

    在對其中key的設計使用上,因為注冊方與調用方都會用到,所以我們將其寫在公共組件內,又因為key會附帶傳一些簡單的值,所以我又加了一個方法對key進行賦值處理操作,目的是為了保證第3條。

    在模塊解耦問題的處理上,我設計了一個繼承AppDelegate方法的協議,暫稱為AppLifeCycle,同時添加了一些方法用于初始化注冊操作。再又設計了一個腳本,可以將遵循AppLifeCycle的實例生成一個plist文件,這樣在App啟動時候,一個方法調用就實現所有路由注冊功能,以此解決4、5。

    對于第7點,在設計之初因為公司還沒有服務器端動態下發的功能,所以又加了中間件做fallBack處理(當然也都沒用上)。

    3. Swifty組件化

    雖然原有的路由設計與模塊解耦方案已經支持現階段業務需求,但是使用上過于復雜,不夠友好,而且也沒用上多少swift的特性,反而這些實現,如果用Objective-c實現起來,會更方便一些,比如腳本生成plist,OC都可以不需要。

    最近有同事在對路由做抽離精簡,僅抽出router部分,主要在接口設計上進行優化。我在看完后對一些功能點提了優化可能,后續一直的交流溝通過程中,突然想到,我可以用Protocol Witness Table來實現這個路由啊!

    其原理是: swift會維護一個Protocol Witness Table, 此表會保存實現了protocol協議的方法的指針地址,當我們調用方法時,是通過獲取對象的內存地址和方法的位移去查找的。

    所以我們可以用一個協議定義入參,一個協議定義實現,同一個Enum(建議使用的)去實現,即可實現功能。

    這種方式類似于target-action,無需注冊,接口約定,還具有其他一些優點:

  • api接口及其簡單,上手難度0
  • 接口可以統一在一個庫內,需要的支持庫也變少了
  • 無硬編碼
  • 那么如此,我們的路由設計的核心代碼,如下:

    public protocol MediatorTargetType {} // 用于接口定義,約束接口public protocol MediatorSourceType { // 用于枚舉實現var viewController: UIViewController? { get } }復制代碼

    target需要遵循的協議就這么些。

    mediator需要遵循的協議與實現:

    public protocol SwiftyMediatorType {func viewController(of target: MediatorTargetType) -> UIViewController? }extension SwiftyMediator: SwiftyMediatorType {public func viewController(of target: MediatorTargetType) -> UIViewController? {guard let t = target as? MediatorSourceType else {print("MEDIATOR WARNINIG: \(target) does not conform to MediatorSourceType")return nil}guard let viewController = t.viewController else { return nil }return viewController} }復制代碼

    以上即是核心代碼。 通過接口收束,需要傳入MediatorTargetType,嘗試轉換成目標類型MediatorSourceType,以此返回viewController。

    4. 使用

    在使用中,我們仍然需要一個公共的組件庫,對路由目標進行定義。假設這個庫叫MediatorTargets,其內容如下:

    public enum ModuleAMediatorType: MediatorTargetType {case home(title: String)case personal(color: UIColor) }復制代碼

    然后在我們寫的模塊庫中,此時我們是路由目標的提供方,如3中核心代碼所示,我們需要 讓ModuleAMediatorType再遵循協議MediatorSourceType,以此支持ModuleAMediatorType返回viewController:

    import SwiftyMediator import MediatorTargetsextension ModuleAMediatorType: MediatorSourceType {public var viewController: UIViewController? {switch self {case .home(let title):let vc = UIViewController()vc.view.backgroundColor = .green vc.title = titlereturn vccase .personal(let color):let vc = PresentedViewController()vc.view.backgroundColor = colorvc.title = "Presented"return vc}} } 復制代碼

    那么實現方的調用,只需要:

    import MediatorTargets import SwiftyMediatorlet vc = Mediator.viewController(of: ModuleAMediatorType.home(title: "Home"))復制代碼

    嗯,就是這么簡單。

    如果只做簡單的模塊間通信,到這是足夠的了, 主要的就是2個協議。

    5. 路由化及動態化

    當然,有些時候我們需要做一些動態化的路由策略,比如做一下動態路由下發。我也對SwiftyMediator做了一些接口適配,使用方式如下:

  • 先將需要路由動態化的已遵循MediatorTargetType的協議ModuleAMediatorType,繼續遵循協議MediatorRoutable,并實現協議:
  • extension ModuleAMediatorType: MediatorRoutable {public init?(url: URLConvertible) {switch url.pattern {case "sy://push":self = .push(title: url.queryParameters["title"] ?? "default")case "sy://present":self = .present(color: UIColor.red)default:return nil }} } 復制代碼
  • 調用SwiftyMediator的func register(_ targetType: MediatorRoutable.Type),注冊ModuleAMediatorType
  • 可選:如需要替換某個路由指向,調用SwiftyMediator的func replace(url: URLConvertible, with replacer: URLConvertible)方法即可
  • 使用url的方式做路由:Mediator.push("sy://push?title=hahaha")
  • 當需要實現動態化的時候,不可避免的要去注冊,而且要實現協議中的枚舉初始化。雖然有些不便,但是在整體的接口收束度上還是挺不錯的。相比較注冊URL的方式來說,這些注冊就少很多了。

    6. 模塊獲取App生命周期

    鑒于目前系統有比較全面的生命周期通知定義,而且不需要在模塊中大量注冊url,所以這部分功能目前在考慮是否需要添加。


    雖然代碼很簡單,實現也很簡單,但是跳出慣性思維,再去嘗試同樣需要很多思考。

    SwiftyMediator,歡迎star。

    其他使用方法見:

    demo

    參考資料:

    WWDC - Protocol Witness Table

    swift的witness table

    URLNavigator

    轉載于:https://juejin.im/post/5c43070e6fb9a049a5713435

    總結

    以上是生活随笔為你收集整理的另辟蹊径--极简Swifty路由的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。