前言
在模組化的過程中,業務模塊間的通信往往是處理最多的.與其應運而生的解決方案有以下幾種:
- 提前註冊服務
-
Runtime
動態發現服務
前輩們在借鑑 web 服務路由設計之後,將服務綁定至固定規則的 URL 上.
-
CTMediator:
Target-Action
形式設計的路由組件. - 其他以統一註冊形式設計的路由.
前情提要
什麼是 Target-Action?
ans: 目標-行爲模式,它貫穿於iOS開發始終, 最常見的便是:
UIButton().addTarget(target: target, action: action, for: event)
什麼是 Target-Action 形式的路由?
ans: 在觸發路由路徑時, 通過 Runtime
機制來發現具體服務,並執行.
相對於提前統一註冊的路由,相當於懶加載.
Khala 路由組件使用
一. 編寫 服務類(路由類)
- 繼承自
NSObject
:Runtime
機制本身便是基於NSObject
. - 聲明
@objc(ClassName)
: 由於Xcode 8.0之後在編譯時會移除未顯式使用的swift類與函數,所以需要加此聲明.(服務類不建議在任何模塊實例化,會破壞設計邏輯) - 聲明
@objcMembers
: 在swift 4.0
中繼承NSObject
的swift class
不再默認全部橋接到objective-c
,如果我們想要使用的話我們就需要在class前面加上@objcMembers
這麼一個關鍵字. - 示例如下如下:
@objc(AModule) @objcMembers
class AModule: NSObject { }
二. 編寫 服務函數(路由函數)
參數類型限制: 只能使用單個
KhalaInfo(集合類型)
與多個KhalaClosure(閉包類型)
第一個參數需要匿名: 方便查找函數, 非匿名
swift
函數橋接至objective-c
時會形成funNameWithParam
結構.(Khala
前期在此花費時間較多, 最後還是採用該折中方案.)-
示例如下如下:
@objc(AModule) @objcMembers class AModule: NSObject,UIApplicationDelegate { func vc() -> UIViewController { let vc = UIViewController() vc.view.backgroundColor = UIColor.red return vc } func action(_ info: KhalaInfo, success: KhalaClosure, failure: KhalaClosure) { success(["success": #function]) failure(["failure": #function]) } }
三. 調用
-
通用型調用
Khala(str: "kf://AModule/forClosures")?.call(blocks: { (item) in print("forClosures block3:", item) },{ (item) in print("forClosure block4:", item) }) let value = Khala(str: "kl://AModule/doSomething")?.call()
-
UIKit
特例化調用:guard let vc = Khala(str: "kl://BModule/vc?style=0")?.viewController else { return } self.navigationController?.pushViewController(vc, animated: true)
四. URL重寫 (KhalaRewrite)
該部分設計來源自nginx: 在某些場景下需要對 URL 進行轉化與攔截, 例如:
服務類與服務函數存在前綴.
接收非標準 URL .
-
URL重定向: 頁面的動態升降級, 示例如下:
let filter = KhalaRewriteFilter { if $0.url.host == "AModule" { var urlComponents = URLComponents(url: $0.url, resolvingAgainstBaseURL: true)! urlComponents.host = "BModule" $0.url = urlComponents.url! } return $0 } Khala.rewrite.add(filter: filter) // "kl://AModule/doSomething" => "kl://BModule/doSomething" let value = Khala(str: "kl://AModule/doSomething")?.call() print(value ?? "nil")
五. UIApplicationDelegate 生命週期分發
部分組件往往依賴於主工程中的AppDelegate
中部分函數.
- 在
Khala
中,需要顯式的在主工程中的AppDelegate
調用與處理相關邏輯. - 服務類需要遵守
UIApplicationDelegate
協議.
主工程AppDelegate
:
@UIApplicationMain
class AppDelegate: UIResponder,UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let list = Khala.appDelegate.application(application, didFinishLaunchingWithOptions: launchOptions)
return true
}
}
組件中服務類:
@objc(AModule) @objcMembers
class AModule: NSObject,UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
print("AModule.didFinishLaunchingWithOptions")
return true
}
}
六. 日誌模塊: KhalaHistory
每一份url請求都將記錄至日誌文件中, 可以在適當的時候提供開發者便利.
-
開啓日誌(默認關閉)
Khala.isEnabledLog = true // or Khala.history.isEnabled = true
文件路徑:
/Documents/khala/logs/
文件內容: 日期 + 時間 + URL + 參數
2018-12-01 02:06:54 kl://SwiftClass/double? {"test":"666"}
2018-12-01 02:06:54 kl://SwiftClass/double {"test":"666"}
七. 擴展機制: KhalaStore
khala 庫中提供了一個空置的類[KhalaStore]用於盛放路由函數對應的本地函數.來簡化本地調用複雜度的問題.
extension KhalaStore {
class func aModule_server(value: Int) -> Int {
return Khala(str: "kf://AModule/server", params: ["value": value])!.call() as! Int
}
}
@objc(AModule) @objcMembers
class AModule: NSObject {
func server(_ info: [String: Any]) -> Int {
return info["value"] as? Int ?? 0
}
}
let value = KhalaStore.aModule_server(value: 46)
ps: KhalaStore 擴展文件建議統一放置.
八. 斷言機制
爲方便開發者使用,添加了部分場景下斷言機制,示例:
khala.iOS Fatal error: [Khala] 未在[AModule]中匹配到函數[server], 請查看函數列表:
0: init
1: doSomething:
2: vc
關閉斷言(默認開啓):
Khala.isEnabledAssert = false
九. 緩存機制: KhalaClass.cache
當路由第一次調用/註冊路由類時,該路由類將被緩存至 KhalaClass.cache 中, 以提高二次查找性能.
當路由類實例化時,該路由類中的函數列表將被緩存至 KhalaClass().methodLists中, 以提高查找性能.
十. 本司基於路由實現的業務架構
僅供參考, 合適纔是最好的.
相關鏈接
Marmot-iOS: 基於 Khala 設計的 hybird(WKWebview
<=> Native
) 通信組件.