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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

另辟蹊径--极简Swifty路由

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

另辟蹊徑--極簡Swifty路由

1. 前言

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

2. 彎路(經(jīng)驗)

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

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

    2.1 實現(xiàn)

    我把router設計成單例,目的是保證其持有的["String": func]的字典的唯一確定性,其中func作為閉包形式,傳入?yún)?shù)返回ViewController。那么注冊環(huán)節(jié)就顯而易見的為register(_ key: String, value: func),調(diào)用就會根據(jù)key,執(zhí)行閉包func返回ViewController,以此解決1。

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

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

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

    3. Swifty組件化

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

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

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

    所以我們可以用一個協(xié)議定義入?yún)?#xff0c;一個協(xié)議定義實現(xiàn),同一個Enum(建議使用的)去實現(xiàn),即可實現(xiàn)功能。

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

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

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

    target需要遵循的協(xié)議就這么些。

    mediator需要遵循的協(xié)議與實現(xiàn):

    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,嘗試轉(zhuǎn)換成目標類型MediatorSourceType,以此返回viewController。

    4. 使用

    在使用中,我們?nèi)匀恍枰粋€公共的組件庫,對路由目標進行定義。假設這個庫叫MediatorTargets,其內(nèi)容如下:

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

    然后在我們寫的模塊庫中,此時我們是路由目標的提供方,如3中核心代碼所示,我們需要 讓ModuleAMediatorType再遵循協(xié)議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}} } 復制代碼

    那么實現(xiàn)方的調(diào)用,只需要:

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

    嗯,就是這么簡單。

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

    5. 路由化及動態(tài)化

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

  • 先將需要路由動態(tài)化的已遵循MediatorTargetType的協(xié)議ModuleAMediatorType,繼續(xù)遵循協(xié)議MediatorRoutable,并實現(xiàn)協(xié)議:
  • 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 }} } 復制代碼
  • 調(diào)用SwiftyMediator的func register(_ targetType: MediatorRoutable.Type),注冊ModuleAMediatorType
  • 可選:如需要替換某個路由指向,調(diào)用SwiftyMediator的func replace(url: URLConvertible, with replacer: URLConvertible)方法即可
  • 使用url的方式做路由:Mediator.push("sy://push?title=hahaha")
  • 當需要實現(xiàn)動態(tài)化的時候,不可避免的要去注冊,而且要實現(xiàn)協(xié)議中的枚舉初始化。雖然有些不便,但是在整體的接口收束度上還是挺不錯的。相比較注冊URL的方式來說,這些注冊就少很多了。

    6. 模塊獲取App生命周期

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


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

    SwiftyMediator,歡迎star。

    其他使用方法見:

    demo

    參考資料:

    WWDC - Protocol Witness Table

    swift的witness table

    URLNavigator

    轉(zhuǎn)載于:https://juejin.im/post/5c43070e6fb9a049a5713435

    總結(jié)

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

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。