設計模式
APP設計模式多種多樣,從最初的MVC到MVVM,再到MVP,VIPER等。越來越多的設計模式被開發出來並得以應用,但不論我們用到哪種設計模式,只需要記住高內聚、低耦合那邊是好的設計模式。在這里筆者整理了一份demo以幫助大家更好的理解Swift版路由機制的設計
APP路由機制出現
筆者了解到最開始分享路由機制的文章是由蘑菇街團隊提供鏈接,其利用url注冊來進行界面推出和傳值。隨后某位大神吐槽其機制有問題鏈接。在這里筆者也開始思考過這個問題,並從他們的思路中得出了適合自己的路由機制設計。路由機制原理、優點等信息網上有太多的資料可供參考,筆者不在這里贅述。下面就為大家介紹筆者的路由機制設計方式
路由機制設計原理
筆者覺得路由機制的設計主要涉及到兩點問題
- 推出界面(確定的目標控制器)
- 數據傳輸(正向傳值和反向傳值)
推出界面
界面推出筆者選擇了最為簡單直接的一種方式,直接通過類名確定需要推出的控制器界面。再由當前控制器選擇進行何種方式的界面推出。在OC中可以直接通過類名轉化為class並生成控制器,但在Swift中由於多了命名空間的原因需要由空間名+類名的方式來生成。具體代碼如下:
//這里的BQRouterCommProtocol是為數據傳輸准備的協議,會在數據傳輸部分進行說明
static func loadVc<T: BaseVc>(vcName:String, spaceName: String? = nil) -> T where T:BQRouterCommProtocol {
var clsName = ""
if let space = spaceName{
clsName = space + "." + vcName
}else {
let spaceName = Bundle.main.infoDictionary!["CFBundleExecutable"] as? String
clsName = spaceName! + "." + vcName
}
let cls = NSClassFromString(clsName) as? BaseVc.Type
let vc = cls?.init()
if let valueVc = vc {
return valueVc as! T
}else {
//當無法生成對應的控制器時,返回一個默認的錯誤控制器用以說明
return ErrorVc() as! T
}
}
數據傳輸
當要推出的控制器視圖有了之后,便要考慮數據傳輸問題,首先是正向傳值,這種比較簡單直接略過,我們需要主要思考的是反向傳值方式,為了做到解耦,筆者最開始思考的方式是直接使用NotificationCenter。考慮到其使用時效率問題(其本質原理是通過KVO方式去進行操作),因此筆者模擬通知中心設計了一個路由通信管理器。
通信管理器設計思路
- 通信管理器注冊進行通信的控制器
- 通信管理器傳輸數據到可接受的控制器
- 當控制器釋放時,從通信管理器中反注冊
先設計通信協議,目的是保證數據傳輸方式的統一和規范
protocol BQRouterCommProtocol:NSObjectProtocol {
var removeIndex: Int { get set } //用於反注冊使用,初始數值小於0
func loadVcInfo(params:Any) //用於正向傳值
func reciveRouterComm(name:Notification.Name, params:Any?) //用於反向傳值
}
為了保證注冊后控制器不被通信管理器強引用,中間使用代理類進行橋接,以便控制器可以正常析構,在反注冊后就移除中間代理類
class BaseVcProxy: NSObject {
weak var vc:BQRouterCommProtocol?
var notifiArr:[Notification.Name] = []
init(vc: BQRouterCommProtocol) {
self.vc = vc
super.init()
}
}
最后進行通信管理
這里模仿通知中心的方式來進行通信管理
//注冊(重復注冊無效)
class public func addRouterComm(names:Notification.Name..., target: BQRouterCommProtocol)
//發送數據
class public func postRouterComm(name:Notification.Name, params:Any? = nil)
//反注冊
class public func romveRouterComm(target: BQRouterCommProtocol)
通信管理器關鍵代碼如下:
private func addComm(names:[Notification.Name], target: BQRouterCommProtocol) {
for weakVc in self.commObjcs {
if let vc = weakVc.vc {
if (vc as! UIViewController) == (target as! UIViewController){
return
}
}
}
let weakVc = BaseVcProxy(vc: target)
weakVc.notifiArr.append(contentsOf: names)
self.commObjcs.append(weakVc)
target.removeIndex = self.commObjcs.index(of: weakVc)!
}
private func postComm(name:Notification.Name, params:Any?) {
for weakVc in self.commObjcs {
if let vc = weakVc.vc {
if weakVc.notifiArr.contains(name) {
vc.reciveRouterComm(name: name, params: params)
}
}
}
}
private func removeComm(target: BQRouterCommProtocol) {
if target.removeIndex >= 0 {
self.commObjcs.remove(at: target.removeIndex)
}
}
到這里大家應該都看出筆者路由設計的概貌了,如還是不太清楚,建議對照demo進行梳理
后記
此路由機制的設計相對來說比較簡單,卻也是路由機制的主干部分。如果想要豐富細化,仍有很多細節可處理。這個就看大家項目的實際需求了。在筆者看來路由機制其實可以作為一種架構設計來說,具體到控制其中又可以分為各種設計模式了。希望這篇文章能讓大家了解到Swift路由設計的方式。如有任何錯誤之處歡迎指正!