先修复一下,错误的场景 删除不必要的钓场资产 修复into场景 update:更新meta文件,修复报错 update:修复资源 修复第一章节建造 修复建造第三章 update:删除多余内容 update:更新README.md update:还原图标 update:更新README update:更新配置
510 lines
19 KiB
Objective-C
510 lines
19 KiB
Objective-C
//
|
|
// TAModuleManager.m
|
|
// Pods
|
|
//
|
|
// Created by wwango on 2022/10/8.
|
|
//
|
|
|
|
#import "TAModuleManager.h"
|
|
#import "TAModuleProtocol.h"
|
|
#import "TAContext.h"
|
|
|
|
#define kTAModuleArrayKey @"moduleClasses"
|
|
#define kTAModuleInfoNameKey @"moduleClass"
|
|
#define kTAModuleInfoLevelKey @"moduleLevel"
|
|
#define kTAModuleInfoPriorityKey @"modulePriority"
|
|
#define kTAModuleInfoHasInstantiatedKey @"moduleHasInstantiated"
|
|
|
|
static NSString *kTASetupSelector = @"modSetUp:";
|
|
static NSString *kTAInitSelector = @"modInit:";
|
|
static NSString *kTASplashSeletor = @"modSplash:";
|
|
static NSString *kTATearDownSelector = @"modTearDown:";
|
|
static NSString *kTAWillResignActiveSelector = @"modWillResignActive:";
|
|
static NSString *kTADidEnterBackgroundSelector = @"modDidEnterBackground:";
|
|
static NSString *kTAWillEnterForegroundSelector = @"modWillEnterForeground:";
|
|
static NSString *kTADidBecomeActiveSelector = @"modDidBecomeActive:";
|
|
static NSString *kTAWillTerminateSelector = @"modWillTerminate:";
|
|
static NSString *kTAUnmountEventSelector = @"modUnmount:";
|
|
static NSString *kTAQuickActionSelector = @"modQuickAction:";
|
|
static NSString *kTAOpenURLSelector = @"modOpenURL:";
|
|
static NSString *kTADidReceiveMemoryWarningSelector = @"modDidReceiveMemoryWaring:";
|
|
static NSString *kTAFailToRegisterForRemoteNotificationsSelector = @"modDidFailToRegisterForRemoteNotifications:";
|
|
static NSString *kTADidRegisterForRemoteNotificationsSelector = @"modDidRegisterForRemoteNotifications:";
|
|
static NSString *kTADidReceiveRemoteNotificationsSelector = @"modDidReceiveRemoteNotification:";
|
|
static NSString *kTADidReceiveLocalNotificationsSelector = @"modDidReceiveLocalNotification:";
|
|
static NSString *kTAWillPresentNotificationSelector = @"modWillPresentNotification:";
|
|
static NSString *kTADidReceiveNotificationResponseSelector = @"modDidReceiveNotificationResponse:";
|
|
static NSString *kTAWillContinueUserActivitySelector = @"modWillContinueUserActivity:";
|
|
static NSString *kTAContinueUserActivitySelector = @"modContinueUserActivity:";
|
|
static NSString *kTADidUpdateContinueUserActivitySelector = @"modDidUpdateContinueUserActivity:";
|
|
static NSString *kTAFailToContinueUserActivitySelector = @"modDidFailToContinueUserActivity:";
|
|
static NSString *kTAHandleWatchKitExtensionRequestSelector = @"modHandleWatchKitExtensionRequest:";
|
|
static NSString *kTAAppCustomSelector = @"modDidCustomEvent:";
|
|
|
|
|
|
@interface TAModuleManager ()
|
|
|
|
@property(nonatomic, strong) NSMutableArray *TAModuleDynamicClasses;
|
|
|
|
@property(nonatomic, strong) NSMutableArray<NSDictionary *> *TAModuleInfos;
|
|
@property(nonatomic, strong) NSMutableArray *TAModules;
|
|
|
|
@property(nonatomic, strong) NSMutableDictionary<NSNumber *, NSMutableArray<id<TAModuleProtocol>> *> *TAModulesByEvent;
|
|
@property(nonatomic, strong) NSMutableDictionary<NSNumber *, NSString *> *TASelectorByEvent;
|
|
|
|
@end
|
|
|
|
|
|
@implementation TAModuleManager
|
|
|
|
|
|
+ (instancetype)sharedManager
|
|
{
|
|
static id sharedManager = nil;
|
|
static dispatch_once_t onceToken = 0;
|
|
dispatch_once(&onceToken, ^{
|
|
sharedManager = [[TAModuleManager alloc] init];
|
|
});
|
|
return sharedManager;
|
|
}
|
|
|
|
- (void)loadLocalModules
|
|
{
|
|
|
|
}
|
|
|
|
- (void)registerDynamicModule:(Class)moduleClass
|
|
{
|
|
[self addModuleFromObject:moduleClass];
|
|
}
|
|
|
|
- (void)unRegisterDynamicModule:(Class)moduleClass {
|
|
if (!moduleClass) {
|
|
return;
|
|
}
|
|
[self.TAModuleInfos filterUsingPredicate:[NSPredicate predicateWithFormat:@"%@!=%@", kTAModuleInfoNameKey, NSStringFromClass(moduleClass)]];
|
|
__block NSInteger index = -1;
|
|
[self.TAModules enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
if ([obj isKindOfClass:moduleClass]) {
|
|
index = idx;
|
|
*stop = YES;
|
|
}
|
|
}];
|
|
if (index >= 0) {
|
|
[self.TAModules removeObjectAtIndex:index];
|
|
}
|
|
[self.TAModulesByEvent enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull key, NSMutableArray<id<TAModuleProtocol>> * _Nonnull obj, BOOL * _Nonnull stop) {
|
|
__block NSInteger index = -1;
|
|
[obj enumerateObjectsUsingBlock:^(id<TAModuleProtocol> _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
if ([obj isKindOfClass:moduleClass]) {
|
|
index = idx;
|
|
*stop = NO;
|
|
}
|
|
}];
|
|
if (index >= 0) {
|
|
[obj removeObjectAtIndex:index];
|
|
}
|
|
}];
|
|
}
|
|
|
|
- (void)registedAllModules
|
|
{
|
|
[self.TAModuleInfos sortUsingComparator:^NSComparisonResult(NSDictionary *module1, NSDictionary *module2) {
|
|
NSNumber *module1Level = (NSNumber *)[module1 objectForKey:kTAModuleInfoLevelKey];
|
|
NSNumber *module2Level = (NSNumber *)[module2 objectForKey:kTAModuleInfoLevelKey];
|
|
if (module1Level.integerValue != module2Level.integerValue) {
|
|
return module1Level.integerValue > module2Level.integerValue;
|
|
} else {
|
|
NSNumber *module1Priority = (NSNumber *)[module1 objectForKey:kTAModuleInfoPriorityKey];
|
|
NSNumber *module2Priority = (NSNumber *)[module2 objectForKey:kTAModuleInfoPriorityKey];
|
|
return module1Priority.integerValue < module2Priority.integerValue;
|
|
}
|
|
}];
|
|
|
|
NSMutableArray *tmpArray = [NSMutableArray array];
|
|
|
|
//module init
|
|
[self.TAModuleInfos enumerateObjectsUsingBlock:^(NSDictionary *module, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
|
|
NSString *classStr = [module objectForKey:kTAModuleInfoNameKey];
|
|
|
|
Class moduleClass = NSClassFromString(classStr);
|
|
BOOL hasInstantiated = ((NSNumber *)[module objectForKey:kTAModuleInfoHasInstantiatedKey]).boolValue;
|
|
if (NSStringFromClass(moduleClass) && !hasInstantiated) {
|
|
id<TAModuleProtocol> moduleInstance = [[moduleClass alloc] init];
|
|
[tmpArray addObject:moduleInstance];
|
|
}
|
|
|
|
}];
|
|
|
|
// [self.BHModules removeAllObjects];
|
|
|
|
[self.TAModules addObjectsFromArray:tmpArray];
|
|
|
|
[self registerAllSystemEvents];
|
|
}
|
|
|
|
- (void)registerCustomEvent:(NSInteger)eventType
|
|
withModuleInstance:(id)moduleInstance
|
|
andSelectorStr:(NSString *)selectorStr {
|
|
if (eventType < 1000) {
|
|
return;
|
|
}
|
|
[self registerEvent:eventType withModuleInstance:moduleInstance andSelectorStr:selectorStr];
|
|
}
|
|
|
|
- (void)triggerEvent:(NSInteger)eventType
|
|
{
|
|
[self triggerEvent:eventType withCustomParam:nil];
|
|
}
|
|
|
|
- (void)triggerEvent:(NSInteger)eventType
|
|
withCustomParam:(NSDictionary *)customParam {
|
|
[self handleModuleEvent:eventType forTarget:nil withCustomParam:customParam];
|
|
}
|
|
|
|
#pragma mark - life loop
|
|
|
|
- (instancetype)init
|
|
{
|
|
self = [super init];
|
|
if (self) {
|
|
self.TAModuleDynamicClasses = [NSMutableArray array];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
|
|
#pragma mark - private
|
|
|
|
- (TAModuleLevel)checkModuleLevel:(NSUInteger)level
|
|
{
|
|
switch (level) {
|
|
case 0:
|
|
return TAModuleBasic;
|
|
break;
|
|
case 1:
|
|
return TAModuleNormal;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
//default normal
|
|
return TAModuleNormal;
|
|
}
|
|
|
|
|
|
- (void)addModuleFromObject:(id)object
|
|
{
|
|
Class class;
|
|
NSString *moduleName = nil;
|
|
|
|
if (object) {
|
|
class = object;
|
|
moduleName = NSStringFromClass(class);
|
|
} else {
|
|
return ;
|
|
}
|
|
|
|
__block BOOL flag = YES;
|
|
[self.TAModules enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
if ([obj isKindOfClass:class]) {
|
|
flag = NO;
|
|
*stop = YES;
|
|
}
|
|
}];
|
|
if (!flag) {
|
|
return;
|
|
}
|
|
|
|
if ([class conformsToProtocol:@protocol(TAModuleProtocol)]) {
|
|
NSMutableDictionary *moduleInfo = [NSMutableDictionary dictionary];
|
|
|
|
BOOL responseBasicLevel = [class instancesRespondToSelector:@selector(basicModuleLevel)];
|
|
|
|
int levelInt = 1;
|
|
|
|
if (responseBasicLevel) {
|
|
levelInt = 0;
|
|
}
|
|
|
|
[moduleInfo setObject:@(levelInt) forKey:kTAModuleInfoLevelKey];
|
|
if (moduleName) {
|
|
[moduleInfo setObject:moduleName forKey:kTAModuleInfoNameKey];
|
|
}
|
|
|
|
[self.TAModuleInfos addObject:moduleInfo];
|
|
|
|
id<TAModuleProtocol> moduleInstance = [[class alloc] init];
|
|
[self.TAModules addObject:moduleInstance];
|
|
[moduleInfo setObject:@(YES) forKey:kTAModuleInfoHasInstantiatedKey];
|
|
[self.TAModules sortUsingComparator:^NSComparisonResult(id<TAModuleProtocol> moduleInstance1, id<TAModuleProtocol> moduleInstance2) {
|
|
NSNumber *module1Level = @(TAModuleNormal);
|
|
NSNumber *module2Level = @(TAModuleNormal);
|
|
if ([moduleInstance1 respondsToSelector:@selector(basicModuleLevel)]) {
|
|
module1Level = @(TAModuleBasic);
|
|
}
|
|
if ([moduleInstance2 respondsToSelector:@selector(basicModuleLevel)]) {
|
|
module2Level = @(TAModuleBasic);
|
|
}
|
|
if (module1Level.integerValue != module2Level.integerValue) {
|
|
return module1Level.integerValue > module2Level.integerValue;
|
|
} else {
|
|
NSInteger module1Priority = 0;
|
|
NSInteger module2Priority = 0;
|
|
if ([moduleInstance1 respondsToSelector:@selector(modulePriority)]) {
|
|
module1Priority = [moduleInstance1 modulePriority];
|
|
}
|
|
if ([moduleInstance2 respondsToSelector:@selector(modulePriority)]) {
|
|
module2Priority = [moduleInstance2 modulePriority];
|
|
}
|
|
return module1Priority < module2Priority;
|
|
}
|
|
}];
|
|
[self registerEventsByModuleInstance:moduleInstance];
|
|
}
|
|
}
|
|
|
|
- (void)registerAllSystemEvents
|
|
{
|
|
[self.TAModules enumerateObjectsUsingBlock:^(id<TAModuleProtocol> moduleInstance, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
[self registerEventsByModuleInstance:moduleInstance];
|
|
}];
|
|
}
|
|
|
|
- (void)registerEventsByModuleInstance:(id<TAModuleProtocol>)moduleInstance
|
|
{
|
|
NSArray<NSNumber *> *events = self.TASelectorByEvent.allKeys;
|
|
[events enumerateObjectsUsingBlock:^(NSNumber * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
[self registerEvent:obj.integerValue withModuleInstance:moduleInstance andSelectorStr:self.TASelectorByEvent[obj]];
|
|
}];
|
|
}
|
|
|
|
- (void)registerEvent:(NSInteger)eventType
|
|
withModuleInstance:(id)moduleInstance
|
|
andSelectorStr:(NSString *)selectorStr {
|
|
SEL selector = NSSelectorFromString(selectorStr);
|
|
if (!selector || ![moduleInstance respondsToSelector:selector]) {
|
|
return;
|
|
}
|
|
NSNumber *eventTypeNumber = @(eventType);
|
|
if (!self.TASelectorByEvent[eventTypeNumber]) {
|
|
[self.TASelectorByEvent setObject:selectorStr forKey:eventTypeNumber];
|
|
}
|
|
if (!self.TAModulesByEvent[eventTypeNumber]) {
|
|
[self.TAModulesByEvent setObject:@[].mutableCopy forKey:eventTypeNumber];
|
|
}
|
|
NSMutableArray *eventModules = [self.TAModulesByEvent objectForKey:eventTypeNumber];
|
|
if (![eventModules containsObject:moduleInstance]) {
|
|
[eventModules addObject:moduleInstance];
|
|
[eventModules sortUsingComparator:^NSComparisonResult(id<TAModuleProtocol> moduleInstance1, id<TAModuleProtocol> moduleInstance2) {
|
|
NSNumber *module1Level = @(TAModuleNormal);
|
|
NSNumber *module2Level = @(TAModuleNormal);
|
|
if ([moduleInstance1 respondsToSelector:@selector(basicModuleLevel)]) {
|
|
module1Level = @(TAModuleBasic);
|
|
}
|
|
if ([moduleInstance2 respondsToSelector:@selector(basicModuleLevel)]) {
|
|
module2Level = @(TAModuleBasic);
|
|
}
|
|
if (module1Level.integerValue != module2Level.integerValue) {
|
|
return module1Level.integerValue > module2Level.integerValue;
|
|
} else {
|
|
NSInteger module1Priority = 0;
|
|
NSInteger module2Priority = 0;
|
|
if ([moduleInstance1 respondsToSelector:@selector(modulePriority)]) {
|
|
module1Priority = [moduleInstance1 modulePriority];
|
|
}
|
|
if ([moduleInstance2 respondsToSelector:@selector(modulePriority)]) {
|
|
module2Priority = [moduleInstance2 modulePriority];
|
|
}
|
|
return module1Priority < module2Priority;
|
|
}
|
|
}];
|
|
}
|
|
}
|
|
|
|
|
|
#pragma mark - property setter or getter
|
|
- (NSMutableArray<NSDictionary *> *)TAModuleInfos {
|
|
if (!_TAModuleInfos) {
|
|
_TAModuleInfos = @[].mutableCopy;
|
|
}
|
|
return _TAModuleInfos;
|
|
}
|
|
|
|
- (NSMutableArray *)TAModules
|
|
{
|
|
if (!_TAModules) {
|
|
_TAModules = [NSMutableArray array];
|
|
}
|
|
return _TAModules;
|
|
}
|
|
|
|
- (NSMutableDictionary<NSNumber *, NSMutableArray<id<TAModuleProtocol>> *> *)TAModulesByEvent
|
|
{
|
|
if (!_TAModulesByEvent) {
|
|
_TAModulesByEvent = @{}.mutableCopy;
|
|
}
|
|
return _TAModulesByEvent;
|
|
}
|
|
|
|
- (NSMutableDictionary<NSNumber *, NSString *> *)TASelectorByEvent
|
|
{
|
|
if (!_TASelectorByEvent) {
|
|
_TASelectorByEvent = @{
|
|
@(TAMSetupEvent):kTASetupSelector,
|
|
@(TAMInitEvent):kTAInitSelector,
|
|
@(TAMTearDownEvent):kTATearDownSelector,
|
|
@(TAMSplashEvent):kTASplashSeletor,
|
|
@(TAMWillResignActiveEvent):kTAWillResignActiveSelector,
|
|
@(TAMDidEnterBackgroundEvent):kTADidEnterBackgroundSelector,
|
|
@(TAMWillEnterForegroundEvent):kTAWillEnterForegroundSelector,
|
|
@(TAMDidBecomeActiveEvent):kTADidBecomeActiveSelector,
|
|
@(TAMWillTerminateEvent):kTAWillTerminateSelector,
|
|
@(TAMUnmountEvent):kTAUnmountEventSelector,
|
|
@(TAMOpenURLEvent):kTAOpenURLSelector,
|
|
@(TAMDidReceiveMemoryWarningEvent):kTADidReceiveMemoryWarningSelector,
|
|
|
|
@(TAMDidReceiveRemoteNotificationEvent):kTADidReceiveRemoteNotificationsSelector,
|
|
@(TAMWillPresentNotificationEvent):kTAWillPresentNotificationSelector,
|
|
@(TAMDidReceiveNotificationResponseEvent):kTADidReceiveNotificationResponseSelector,
|
|
|
|
@(TAMDidFailToRegisterForRemoteNotificationsEvent):kTAFailToRegisterForRemoteNotificationsSelector,
|
|
@(TAMDidRegisterForRemoteNotificationsEvent):kTADidRegisterForRemoteNotificationsSelector,
|
|
|
|
@(TAMDidReceiveLocalNotificationEvent):kTADidReceiveLocalNotificationsSelector,
|
|
|
|
@(TAMWillContinueUserActivityEvent):kTAWillContinueUserActivitySelector,
|
|
|
|
@(TAMContinueUserActivityEvent):kTAContinueUserActivitySelector,
|
|
|
|
@(TAMDidFailToContinueUserActivityEvent):kTAFailToContinueUserActivitySelector,
|
|
|
|
@(TAMDidUpdateUserActivityEvent):kTADidUpdateContinueUserActivitySelector,
|
|
|
|
@(TAMQuickActionEvent):kTAQuickActionSelector,
|
|
@(TAMDidCustomEvent):kTAAppCustomSelector,
|
|
}.mutableCopy;
|
|
}
|
|
return _TASelectorByEvent;
|
|
}
|
|
|
|
#pragma mark - module protocol
|
|
- (void)handleModuleEvent:(NSInteger)eventType
|
|
forTarget:(id<TAModuleProtocol>)target
|
|
withCustomParam:(NSDictionary *)customParam
|
|
{
|
|
switch (eventType) {
|
|
case TAMInitEvent:
|
|
//special
|
|
[self handleModulesInitEventForTarget:nil withCustomParam :customParam];
|
|
break;
|
|
case TAMTearDownEvent:
|
|
//special
|
|
[self handleModulesTearDownEventForTarget:nil withCustomParam:customParam];
|
|
break;
|
|
default: {
|
|
NSString *selectorStr = [self.TASelectorByEvent objectForKey:@(eventType)];
|
|
[self handleModuleEvent:eventType forTarget:nil withSeletorStr:selectorStr andCustomParam:customParam];
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
- (void)handleModulesInitEventForTarget:(id<TAModuleProtocol>)target
|
|
withCustomParam:(NSDictionary *)customParam
|
|
{
|
|
TAContext *context = [TAContext shareInstance].copy;
|
|
|
|
NSArray<id<TAModuleProtocol>> *moduleInstances;
|
|
if (target) {
|
|
moduleInstances = @[target];
|
|
} else {
|
|
moduleInstances = [self.TAModulesByEvent objectForKey:@(TAMInitEvent)];
|
|
}
|
|
|
|
[moduleInstances enumerateObjectsUsingBlock:^(id<TAModuleProtocol> moduleInstance, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
__weak __typeof(&*self) wself = self;
|
|
void ( ^ bk )(void);
|
|
bk = ^(){
|
|
__strong __typeof(&*self) sself = wself;
|
|
if (sself) {
|
|
if ([moduleInstance respondsToSelector:@selector(modInit:)]) {
|
|
[moduleInstance modInit:context];
|
|
}
|
|
}
|
|
};
|
|
|
|
if ([moduleInstance respondsToSelector:@selector(async)]) {
|
|
BOOL async = [moduleInstance async];
|
|
|
|
if (async) {
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
bk();
|
|
});
|
|
|
|
} else {
|
|
bk();
|
|
}
|
|
} else {
|
|
bk();
|
|
}
|
|
}];
|
|
}
|
|
|
|
- (void)handleModulesTearDownEventForTarget:(id<TAModuleProtocol>)target
|
|
withCustomParam:(NSDictionary *)customParam
|
|
{
|
|
TAContext *context = [TAContext shareInstance].copy;
|
|
|
|
NSArray<id<TAModuleProtocol>> *moduleInstances;
|
|
if (target) {
|
|
moduleInstances = @[target];
|
|
} else {
|
|
moduleInstances = [self.TAModulesByEvent objectForKey:@(TAMTearDownEvent)];
|
|
}
|
|
|
|
//Reverse Order to unload
|
|
for (int i = (int)moduleInstances.count - 1; i >= 0; i--) {
|
|
id<TAModuleProtocol> moduleInstance = [moduleInstances objectAtIndex:i];
|
|
if (moduleInstance && [moduleInstance respondsToSelector:@selector(modTearDown:)]) {
|
|
[moduleInstance modTearDown:context];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- (void)handleModuleEvent:(NSInteger)eventType
|
|
forTarget:(id<TAModuleProtocol>)target
|
|
withSeletorStr:(NSString *)selectorStr
|
|
andCustomParam:(NSDictionary *)customParam
|
|
{
|
|
TAContext *context = [TAContext shareInstance].copy;
|
|
if (!selectorStr.length) {
|
|
selectorStr = [self.TASelectorByEvent objectForKey:@(eventType)];
|
|
}
|
|
SEL seletor = NSSelectorFromString(selectorStr);
|
|
if (!seletor) {
|
|
selectorStr = [self.TASelectorByEvent objectForKey:@(eventType)];
|
|
seletor = NSSelectorFromString(selectorStr);
|
|
}
|
|
NSArray<id<TAModuleProtocol>> *moduleInstances;
|
|
if (target) {
|
|
moduleInstances = @[target];
|
|
} else {
|
|
moduleInstances = [self.TAModulesByEvent objectForKey:@(eventType)];
|
|
}
|
|
[moduleInstances enumerateObjectsUsingBlock:^(id<TAModuleProtocol> moduleInstance, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
if ([moduleInstance respondsToSelector:seletor]) {
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
|
[moduleInstance performSelector:seletor withObject:context];
|
|
#pragma clang diagnostic pop
|
|
}
|
|
}];
|
|
}
|
|
|
|
|
|
@end
|