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

posted @ 2020-04-01 16:36  裸奔的小鸟  阅读(1681)  评论(0编辑  收藏  举报