大佬好,可以加个优先级参数吗,排序是很重要的 https://github.com/youzan/Bifrost 这个好像可以
https://github.com/youzan/Bifrost ,可以加上吗,谢谢
` #import <Foundation/Foundation.h> #import <UIKit/UIKit.h>
#define HH_EXPORT_SERVICE(name, sort) \
- (void)load {[[HHAppServiceManager sharedManager] registerService:[self new]];} \
- (NSString *)serviceName { return @#name; } \
- (NSNumber *)priority { return @(sort); }
NS_ASSUME_NONNULL_BEGIN
@protocol HHAppService <UIApplicationDelegate>
@required
- (NSString *)serviceName;
- (NSNumber *)priority; @end
@interface HHAppServiceManager : NSObject
- (instancetype)sharedManager;
-
(void)registerService:(id<HHAppService>)service;
-
(BOOL)proxyCanResponseToSelector:(SEL)aSelector;
-
(void)proxyForwardInvocation:(NSInvocation *)anInvocation;
@end
NS_ASSUME_NONNULL_END `
` #import "HHAppServiceManager.h" #import <objc/runtime.h> #import <objc/message.h>
@interface HHAppServiceManager () @property (nonatomic, strong) Class<UIApplicationDelegate> appDelegateClass; @property (nonatomic, strong) NSMutableDictionary<NSString*, id<HHAppService>> servicesMap; @property (nonatomic, strong) NSMutableDictionary<NSNumber, NSString*> *servicesSort; @end
// 由子类实现服务代理方法,父类负责把这些实现添加到 ApplicationDelegate 中 // 这些都需要在 ApplicationDelegate 实例创建之前执行 @implementation HHAppServiceManager
-
(instancetype)sharedManager { static HHAppServiceManager *_sharedManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _sharedManager = [HHAppServiceManager new]; });
return _sharedManager; }
-
(instancetype)init { if (self = [super init]) { self.servicesMap = [NSMutableDictionary dictionary]; self.servicesSort = [NSMutableDictionary dictionary]; } return self; }
-
(void)registerService:(id<HHAppService>)service { if (!service) { return; } id<HHAppService> pre = self.servicesMap[[service serviceName]]; if (pre) { if ([service isKindOfClass:[pre class]]) { self.servicesMap[[service serviceName]] = service; self.servicesSort[[service priority]] = [service serviceName]; } else { NSAssert([pre isKindOfClass:[service class]], @"Tried to register both %@ and %@ as the handler of %@ service.
Cannot determine the right class to use because neither inherits from the other.", [pre class], [service class], [service serviceName]); } } else { self.servicesMap[[service serviceName]] = service; self.servicesSort[[service priority]] = [service serviceName]; } } -
(NSArray *)sortKeysByIntValue:(NSDictionary *)dictionary { NSArray *sortedKeys = [dictionary keysSortedByValueUsingComparator:^NSComparisonResult(id obj1, id obj2) { int v1 = [obj1 intValue]; int v2 = [obj2 intValue]; if (v1 < v2) return NSOrderedAscending; else if (v1 > v2) return NSOrderedDescending; else return NSOrderedSame; }]; return sortedKeys; }
#pragma mark - #pragma mark Proxy
-
(BOOL)proxyCanResponseToSelector:(SEL)aSelector { __block IMP imp = NULL;
NSArray *sortedKeys = [self sortKeysByIntValue:self.servicesSort]; [sortedKeys enumerateObjectsUsingBlock:^(id _Nonnull key, NSUInteger idx, BOOL * _Nonnull stop) { id<HHAppService> obj = self.servicesMap[self.servicesSort[key]]; 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 *)objcTypesFromSignature:(NSMethodSignature *)signature { NSMutableString *types = [NSMutableString stringWithFormat:@"%s", signature.methodReturnType?:"v"]; for (NSUInteger i = 0; i < signature.numberOfArguments; i ++) { [types appendFormat:@"%s", [signature getArgumentTypeAtIndex:i]]; } return [types copy]; }
-
(void)proxyForwardInvocation:(NSInvocation *)anInvocation {
NSMethodSignature *signature = anInvocation.methodSignature; NSUInteger argCount = signature.numberOfArguments; __block BOOL returnValue = NO; NSUInteger returnLength = signature.methodReturnLength; void * returnValueBytes = NULL; if (returnLength > 0) { returnValueBytes = alloca(returnLength); }
NSArray *sortedKeys = [self sortKeysByIntValue:self.servicesSort]; [sortedKeys enumerateObjectsUsingBlock:^(id _Nonnull key, NSUInteger idx, BOOL * _Nonnull stop) { id<HHAppService> obj = self.servicesMap[self.servicesSort[key]];
if ( ! [obj respondsToSelector:anInvocation.selector]) { return; } // check the signature NSAssert([[self objcTypesFromSignature:signature] isEqualToString:[self objcTypesFromSignature:[(id)obj methodSignatureForSelector:anInvocation.selector]]], @"Method signature for selector (%@) on (%@ - `%@`) is invalid. \ Please check the return value type and arguments type.", NSStringFromSelector(anInvocation.selector), obj.serviceName, obj); // copy the invokation NSInvocation *invok = [NSInvocation invocationWithMethodSignature:signature]; invok.selector = anInvocation.selector; // copy arguments for (NSUInteger i = 0; i < argCount; i ++) { const char * argType = [signature getArgumentTypeAtIndex:i]; NSUInteger argSize = 0; NSGetSizeAndAlignment(argType, &argSize, NULL); void * argValue = alloca(argSize); [anInvocation getArgument:&argValue atIndex:i]; [invok setArgument:&argValue atIndex:i]; } // reset the target invok.target = obj; // invoke [invok invoke]; // get the return value if (returnValueBytes) { [invok getReturnValue:returnValueBytes]; returnValue = returnValue || *((BOOL *)returnValueBytes); }}];
// set return value if (returnValueBytes) { [anInvocation setReturnValue:returnValueBytes]; } }
@end
`
楼主代码很棒,我稍微改了一下,支持优先级priority,供大家参考