模块管理
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@protocol RCEAppDelegateService<UIApplicationDelegate>
@required
- (NSString *)serviceName;
@end
@interface RCEAppDelegateServiceManager : NSObject
+ (instancetype)sharedServiceManager;
/**
注册子模块
*/
- (void)registerService:(id <RCEAppDelegateService>)service;
/**
子模块是否可以响应消息
*/
- (BOOL)canResponseToSelector:(SEL)aSelector;
/**
子模块进行消息转发
*/
- (void)submoduleForwardInvocation:(NSInvocation *)invocation;
@end
#import "RCEAppDelegateServiceManager.h"
#import <objc/message.h>
@interface RCEAppDelegateServiceManager()
@property(nonatomic , strong)NSMutableArray<id <RCEAppDelegateService> > *services;
@end
@implementation RCEAppDelegateServiceManager
+(instancetype)sharedServiceManager{
static dispatch_once_t onceToken;
static RCEAppDelegateServiceManager *manager = nil;
dispatch_once(&onceToken, ^{
manager = [[RCEAppDelegateServiceManager alloc] init];
});
return manager;
}
-(instancetype)init{
if (self = [super init]) {
self.services = [NSMutableArray array];
}
return self;
}
- (void)registerService:(id <RCEAppDelegateService>)service{
if (!service) {
return;
}
__block BOOL has = NO;
[self.services enumerateObjectsUsingBlock:^(id<RCEAppDelegateService> _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isKindOfClass:[service class]]) {
obj = service;
has = YES;
}
}];
if (!has) {
[self.services addObject:service];
}
}
- (BOOL)canResponseToSelector:(SEL)aSelector{
__block IMP imp = NULL;
[self.services enumerateObjectsUsingBlock:^(id<RCEAppDelegateService> _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj respondsToSelector:aSelector]) {
imp = [(id)obj methodForSelector:aSelector];
NSMethodSignature *signature = [(id)obj methodSignatureForSelector:aSelector];
if (signature.methodReturnLength > 0 && strcmp(signature.methodReturnType, @encode(BOOL)) != 0) {
imp = NULL;
}
*stop = YES;
}
}];
return imp != NULL && imp != _objc_msgForward;
}
-(NSString *)methodSignature:(NSMethodSignature *)methodSignature{
NSMutableString *signature = [NSMutableString stringWithFormat:@"%s",methodSignature.methodReturnType?:"v"];
for (NSInteger i = 0 ; i > methodSignature.numberOfArguments; i ++) {
const char *type = [methodSignature getArgumentTypeAtIndex:i];
[signature appendString:[NSString stringWithFormat:@"%s",type]];
}
return signature;
}
- (void)submoduleForwardInvocation:(NSInvocation *)invocation{
SEL selector = invocation.selector;
NSMethodSignature *signature = invocation.methodSignature;
NSInteger length = signature.methodReturnLength;
void *returnBytes = NULL;
if (length > 0) {
returnBytes = alloca(length);
}
[self.services enumerateObjectsUsingBlock:^(id<RCEAppDelegateService> _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (![obj respondsToSelector:selector]) {
return ;
}
// check
NSString *targetSignature = [self methodSignature:invocation.methodSignature];
NSString *submodelSignature = [self methodSignature:[(id)obj methodSignatureForSelector:selector]];
NSAssert([targetSignature isEqualToString:submodelSignature ],@"method must equal " );
// submodule to invok
NSInvocation *invok = [NSInvocation invocationWithMethodSignature:signature];
NSUInteger argCount = signature.numberOfArguments;
for (NSInteger i = 0 ; i < argCount; i ++) {
const char *type = [signature getArgumentTypeAtIndex:i];
NSUInteger size = 0;
NSGetSizeAndAlignment(type, &size, NULL);
void *value = alloca(size);
// target(self) sel(_cmd)
[invocation getArgument:&value atIndex:i];
[invok setArgument:&value atIndex:i];
}
invok.selector = selector;
invok.target = obj;
[invok invoke];
if (returnBytes) {
[invok getReturnValue:returnBytes];
}
if (returnBytes) {
[invocation setReturnValue:returnBytes];
}
}];
}
@end
采用宏定义方式, 各模块自己注册即可
#import <UIKit/UIKit.h>
#import "RCEAppDelegateServiceManager.h"
#define RCE_REGISTER_SERVICE_NAME(name) \
+(void)load{\
[[RCEAppDelegateServiceManager sharedServiceManager] registerService:[self new]];\
}\
-(NSString *)serviceName{\
return @#name;\
}
@interface RCEAppDelegate : UIResponder<UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
#import "RCEAppDelegate.h"
#import <objc/message.h>
@implementation RCEAppDelegate
- (NSArray<NSString *> *)methods{
static dispatch_once_t onceToken;
static NSMutableArray *methodList = nil;
dispatch_once(&onceToken, ^{
unsigned int count;
struct objc_method_description *lists = protocol_copyMethodDescriptionList(@protocol(UIApplicationDelegate), NO, YES, &count);
methodList = [NSMutableArray array];
for (NSInteger i = 0; i < count; i ++ ) {
struct objc_method_description method = lists[i];
SEL selector = method.name;
[methodList addObject:NSStringFromSelector(selector)];
}
});
return methodList;
}
-(BOOL)respondsToSelector:(SEL)aSelector{
IMP imp = [self methodForSelector:aSelector];
BOOL has = imp != nil && imp !=_objc_msgForward;
if (!has && [[self methods] containsObject:NSStringFromSelector(aSelector)]) {
has = [[RCEAppDelegateServiceManager sharedServiceManager] canResponseToSelector:aSelector];
}
return has;
}
-(void)forwardInvocation:(NSInvocation *)anInvocation{
[[RCEAppDelegateServiceManager sharedServiceManager] submoduleForwardInvocation:anInvocation];
}
@end
示例1
#import <Foundation/Foundation.h>
#import "RCEAppDelegate.h"
@interface NotificationService : NSObject<RCEAppDelegateService>
@end
#import "NotificationService.h"
@implementation NotificationService
RCE_REGISTER_SERVICE_NAME(NotificationService);
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSLog(@"我是notification");
return YES;
}
@end
示例2
#import <Foundation/Foundation.h>
#import "RCEAppDelegate.h"
@interface RootWindow : NSObject<RCEAppDelegateService>
@end
#import "RootWindow.h"
#import "ViewController.h"
@implementation RootWindow
RCE_REGISTER_SERVICE_NAME(RootWindow)
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
application.delegate.window = window;
ViewController* dvc = [[ViewController alloc] init];
UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:dvc];
window.rootViewController = nav;
[window makeKeyAndVisible];
return YES;
}
@end
入口
#import <UIKit/UIKit.h>
#import "RCEAppDelegate.h"
@interface AppDelegate : RCEAppDelegate <UIApplicationDelegate>
@end
#import "AppDelegate.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(@"");
if ([super respondsToSelector:@selector(application:didFinishLaunchingWithOptions:)]) {
[super application:application didFinishLaunchingWithOptions:launchOptions];
}
return YES;
}
@end