Swift 路由機制設計


設計模式

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方式去進行操作),因此筆者模擬通知中心設計了一個路由通信管理器。

通信管理器設計思路
  1. 通信管理器注冊進行通信的控制器
  2. 通信管理器傳輸數據到可接受的控制器
  3. 當控制器釋放時,從通信管理器中反注冊

先設計通信協議,目的是保證數據傳輸方式的統一和規范

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路由設計的方式。如有任何錯誤之處歡迎指正!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM