Swift 模塊化框架的實現以及模塊之間的解藕


一般比較大的項目都會使用到模塊化的方式來管理各個組件, 這樣每個模塊的owner只需要專注於該模塊的開發,而不需要關心其他模塊. 於是本文簡單介紹一下Swift模塊化框架的簡單實現.

 

模塊化實現

整體思路是這樣的,  app啟動后先初始化一個模塊管理類ModuleManager, 然后由ModuleManager去初始化各個模塊. 可以參考下面的結構圖

App 啟動之后調用ModuleManager的 applicationDidFinishLaunching等方法, 然后ModuleManager 負責調用每個模塊的applicationDidFinishLaunching等方法.

不分實現的代碼如下:

  • 先定義所有模塊都必須遵循的協議 ModuleProtocol , ModuleProtocol是繼承自UIApplicationDelegate
  • 然后根據模塊的名字注冊該模塊,比如這個地方是注冊"ModuleA.ModuleClassA" (注意swift里是根據 "#模塊名.#類名" 的形式來找到該類)
  • 然后在 applicationDidFinishLaunching 方法中遍歷, 從而調用所有已注冊模塊的applicationDidFinishLaunching方法
@objc public protocol ModuleProtocol:UIApplicationDelegate {
   static func create() -> ModuleProtocol?
}
func registerModule(_ moduleName:String){
    guard let moduleClass:AnyClass = NSClassFromString(moduleName) else{return}
    var moduleContext:ModuleContext = ModuleContext()
    moduleContext.moduleClass = moduleClass
    moduleContext.moduleName = NSStringFromClass(moduleClass)
    guard let moduleObject:ModuleProtocol = (moduleContext.moduleClass as! ModuleProtocol.Type).create() else {
        return
    }
    moduleContext.modueleObject = moduleObject
    moduleContextArray.append(moduleContext)
}
public func applicationDidFinishLaunching(_ application: UIApplication) {
    for context in moduleContextArray {
        if (context.modueleObject?.responds(to: #selector(applicationDidFinishLaunching(_:))))!{
            context.modueleObject?.applicationDidFinishLaunching?(application)
        }
    }
}

 

模塊之間的解藕

開發過程中經常會遇到這樣的情況, 模塊A 需要調用 模塊B的方法, 模塊B 需要調用 模塊C 的方法, 而模塊C 又調用了 模塊A 的方法. 從而導致循環依賴.

為了解決這樣的問題, 就需要對各個模塊進行解藕. 具體思路是這樣的: 對於每一個需要被外部調用的模塊(比如ModuleA), 我們會抽離出來一個獨立的service模塊 ModuleAService 以供給外部模塊的調用. 這樣ModuleB 只需要依賴 ModuleAService 而不需要依賴 ModuleA, 從而完成解藕

下面是部分實現代碼:

  • 首先定義一個所有Service模塊都必須遵循的協議ServiceProtocol
  • 然后注冊所有的Service模塊, 比如"ModuleAService.ModuleAService"
  • 在ModuleB中就可以獲取 ModuleAService 協議的實例, 並調用該協議的方法 majorFunctionInModuleA. 由於ModuleA是遵循ModuleAService協議的, 並且已經實現了協議方法majorFunctionInModuleA,所以最終達到了在ModuleB中不引入ModuleA就調用ModuleA的方法的目的.
@objc public protocol ServiceProtocol{
    
}
func registerService(_ serviceName:String){
    guard let serviceClass:AnyClass = NSClassFromString(serviceName) else{
        return
    }
    var count:UInt32 = 0
    guard let protocolList = class_copyProtocolList(serviceClass, &count) else{
        return
    }
    var serviceProtocolList:[Protocol] = []
    for i in 0..<count {
        let foundServiceProtocols = findServiceProtocols(protocolList[Int(i)])
        serviceProtocolList.append(contentsOf: foundServiceProtocols)
    }
    
    for serviceProtocol in serviceProtocolList {
        setServiceClass(serviceClass, forProtocol: serviceProtocol)
    }
}
let instanceList:[ModuleAService] = ModuleManager.sharedInstance.servicesForProtocol(ModuleAService.self) as! [ModuleAService]
let instance:ModuleAService = instanceList.first!
instance.majorFunctionInModuleA()
public class ModuleAServiceClass: NSObject,ModuleAService  {
    
    public func majorFunctionInModuleA() {
        let moduleA = ModuleClassA()
        moduleA.majorFunctionInModuleA()
    }
    
}

 

完整的代碼請參考: https://github.com/jimwan/Swift-modularization


免責聲明!

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



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