注册
iOS

基于协议的业务模块路由管理

概述


这是一个关于业务模块与路由权限的管理方案,用于增强在模块化架构场景下,业务模块的健壮性。


  • 通过对App生命周期的转发,来解除App入口与业务模块管理逻辑的耦合。
  • 通过协议来管理API路由,通过注册制实现API的服务发现。

业务模块


50cc1079529bfefc8d6a42de65b11044.png


重新组织后,业务模块的管理会变得松散,容易实现插拔复用。


协议

public protocol SpaceportModuleProtocol {
   var loaded: Bool { get set}
   /// 决定模块的加载顺序,数字越大,优先级越高
   /// - Returns: 默认优先级为1000
   static func modulePriority() -> Int
   /// 加载
   func loadModule()
   /// 卸载
   func unloadModule()

   /// UIApplicationDidFinishLaunching
   func applicationDidFinishLaunching(notification: Notification)
   /// UIApplicationWillResignActive
   func applicationWillResignActive(notification: Notification)
   /// UIApplicationDidBecomeActive
   func applicationDidBecomeActive(notification: Notification)
   /// UIApplicationDidEnterBackground
   func applicationDidEnterBackground(notification: Notification)
   /// UIApplicationWillEnterForeground
   func applicationWillEnterForeground(notification: Notification)
   /// UIApplicationWillTerminate
   func applicationWillTerminate(notification: Notification)
}

特性


  • 实现模块加载/卸载保护,模块只会加载/卸载一次。
  • 同一个模块的注册是替换制,新模块会替代旧模块。
  • 提供模块优先级配置,优先级高的模块会更早加载并响应Application的生命周期回调。

最佳实践

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
   var window: UIWindow?
   func application(_ application: UIApplication, didFinishLaunchingWithOptionslaunchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
       setupModules()
// ......
       return true
   }
 
   func setupModules() {
       var modules: [SpaceportModuleProtocol] = [
           LoggerModule(),             // 4000
           NetworkModule(),            // 3000
           FirebaseModule(),           // 2995
           RouterModule(),             // 2960
           DynamicLinkModule(),        // 2950
           UserEventRecordModule(),    // 2900
           AppConfigModule(),          // 2895
           MediaModule(),              // 2800
           AdModule(),                 // 2750
           PurchaseModule(),           // 2700
           AppearanceModule(),         // 2600
           AppstoreModule(),           // 2500
           MLModule()                  // 2500
       ]
#if DEBUG
       modules.append(DebugModule())   // 2999
#endif
       Spaceport.shared.registerModules(modules)
       Spaceport.shared.enableAllModules()
   }
}

协议路由


协议路由


通过路由的协议化管理,实现模块/组件之间通信的权限管理。


  • 服务方通过Router Manger注册API协议,可以根据场景提供不同的协议版本。
    • 业务方通过Router Manager发现并使用API协议。


最佳实践


实现API协议

protocol ResultVCRouterAPI {
   @MainActor func vc(from: ResultVCFromType, project: Project) throws -> ResultVC
   @MainActor func vcFromPreview(serviceType: EnhanceServiceType, originalImage:UIImage, enhancedImage: UIImage) async throws -> ResultVC
}

class ResultVCRouter: ResultVCRouterAPI {
   @MainActor func vc(from: ResultVCFromType, project: Project) throws -> ResultVC {
       let vc = ResultVC()
       vc.modalPresentationStyle = .overCurrentContext
       try vc.vm.config(project: project)
       vc.vm.fromType = from
       return vc
   }

   @MainActor func vcFromPreview(serviceType: EnhanceServiceType, originalImage:UIImage, enhancedImage: UIImage) async throws -> ResultVC {
       let vc = ResultVC()
       vc.modalPresentationStyle = .overCurrentContext
       try await vc.vm.config(serviceType: serviceType, originalImage: originalImage,enhancedImage: enhancedImage)
       return vc
   }
}

注册API协议

public class RouterManager: SpaceportRouterService {
   public static let shared = RouterManager()
   private override init() {}
   static func API<T>(_ key: TypeKey<T>) -> T? {
       return shared.getRouter(key)
   }
}

class RouterModule: SpaceportModuleProtocol {
   var loaded = false
   static func modulePriority() -> Int { return 2960 }
   func loadModule() {
     // 注册API
       RouterManager.shared.register(TypeKey(ResultVCRouterAPI.self), router:ResultVC())
   }
   func unloadModule() { }
}

使用协议

// 通过 RouterManager 获取可用API
guard let api = RouterManager.API(TypeKey(ResultVCRouterAPI.self)) else { return }
let vc = try await api.vcFromPreview(serviceType: .colorize, originalImage:originalImage, enhancedImage: enhancedImage)
self.present(vc, animated: false)

总结


我们的业务向模块化、组件化架构演化的过程中,逐步出现跨组件调用依赖嵌套,插拔困难等问题。


通过抽象和简化,设计了这个方案,作为后续业务组件化的规范之一。通过剥离业务模块的生命周期,以及统一通信的方式,可以减缓业务增长带来的代码劣化问题。


作者:Ginhoor大帅
链接:https://juejin.cn/post/7198388410381402168
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册