|
@@ -0,0 +1,100 @@
|
|
|
+//
|
|
|
+// XCMEngine.m
|
|
|
+// XCComponentization
|
|
|
+//
|
|
|
+// Created by 邢铖 on 2023/7/8.
|
|
|
+//
|
|
|
+
|
|
|
+#import "XCMEngine.h"
|
|
|
+#import <objc/runtime.h>
|
|
|
+
|
|
|
+@interface XCMRuntimeModuleInfo : NSObject
|
|
|
+
|
|
|
+@property (nonatomic, assign) NSInteger priority;
|
|
|
+@property (nonatomic, copy) NSString *className;
|
|
|
+@property (nonatomic, strong) id<XCModuleProtocol> classInstance;
|
|
|
+
|
|
|
+@end
|
|
|
+
|
|
|
+@implementation XCMRuntimeModuleInfo
|
|
|
+
|
|
|
+@end
|
|
|
+
|
|
|
+@interface XCMEngine ()
|
|
|
+
|
|
|
+@property (nonatomic, strong) NSMutableDictionary<NSString *, XCMRuntimeModuleInfo *> *modules;
|
|
|
+@property (nonatomic, strong) NSMutableArray<XCMRuntimeModuleInfo *> *sortedModules;
|
|
|
+
|
|
|
+@end
|
|
|
+
|
|
|
+@implementation XCMEngine
|
|
|
+
|
|
|
+- (instancetype)init {
|
|
|
+ self = [super init];
|
|
|
+ if (self) {
|
|
|
+ self.modules = [NSMutableDictionary new];
|
|
|
+ self.sortedModules = [NSMutableArray new];
|
|
|
+ }
|
|
|
+ return self;
|
|
|
+}
|
|
|
+
|
|
|
++ (XCMEngine *)sharedEngine {
|
|
|
+ static XCMEngine *engineInstance;
|
|
|
+ static dispatch_once_t onceToken;
|
|
|
+ dispatch_once(&onceToken, ^{
|
|
|
+ engineInstance = [XCMEngine new];
|
|
|
+ });
|
|
|
+ return engineInstance;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)registerModule:(Class)moduleClass {
|
|
|
+ [self registerModule:moduleClass shouldInit:false];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)registerModule:(Class)moduleClass shouldInit:(BOOL)shouldInit {
|
|
|
+ NSString *className = NSStringFromClass(moduleClass);
|
|
|
+ if (self.modules[className]) {
|
|
|
+ @throw [NSException exceptionWithName:NSInvalidArgumentException
|
|
|
+ reason:[NSString stringWithFormat:@"Module %@: already registered", className]
|
|
|
+ userInfo:nil];
|
|
|
+ }
|
|
|
+ id<XCModuleProtocol> instance = class_createInstance(moduleClass, 0);
|
|
|
+ XCMRuntimeModuleInfo *moduleInfo = [XCMRuntimeModuleInfo new];
|
|
|
+ moduleInfo = [moduleInfo init];
|
|
|
+ moduleInfo.className = className;
|
|
|
+ moduleInfo.classInstance = instance;
|
|
|
+ moduleInfo.priority = instance.modulePriority;
|
|
|
+ self.modules[className] = moduleInfo;
|
|
|
+ [self.sortedModules addObject:moduleInfo];
|
|
|
+ [self.sortedModules sortUsingComparator:^(XCMRuntimeModuleInfo *left, XCMRuntimeModuleInfo *right) {
|
|
|
+ return left.priority - right.priority;
|
|
|
+ }];
|
|
|
+ [instance moduleRegister:self.context];
|
|
|
+ if (shouldInit) {
|
|
|
+ [instance moduleInit:self.context];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)unregisterModule:(Class)moduleClass {
|
|
|
+ NSString *className = NSStringFromClass(moduleClass);
|
|
|
+ XCMRuntimeModuleInfo *moduleInfo = self.modules[className];
|
|
|
+ if (!moduleInfo) {
|
|
|
+ @throw [NSException exceptionWithName:NSInvalidArgumentException
|
|
|
+ reason:[NSString stringWithFormat:@"Module %@: not registered", className]
|
|
|
+ userInfo:nil];
|
|
|
+ }
|
|
|
+ id<XCModuleProtocol> instance = moduleInfo.classInstance;
|
|
|
+ [instance moduleTearDown:self.context];
|
|
|
+ self.modules[className] = nil;
|
|
|
+ [self.sortedModules removeObject:moduleInfo];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)forEachModules:(BOOL (^)(id<XCModuleProtocol> _Nonnull))forEachModuleBlock {
|
|
|
+ for (XCMRuntimeModuleInfo *moduleInfo in self.sortedModules) {
|
|
|
+ if (!forEachModuleBlock(moduleInfo.classInstance)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@end
|