zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    VB.Net常用数学函数整理
    VB6转换C#2010步骤及工具
    通用MD5加密演示
    一行代码解决VB.NET中Dialog窗体销毁不刷新主窗体
    JavaScript中defer 和onload的执行顺序
    XML读取事例程序
    C#正则表达式使用指引
    使用Response.ContentType 来控制下载文件的类型
    重载、重写的简易解释
    西历转和历函数
  • 原文地址:https://www.cnblogs.com/streakingBird/p/12613563.html
Copyright © 2011-2022 走看看