Protocol协议分发器
- 用途: 能够制定多个对象实现
, 同一个代理方法,可以在多个对象中同时实现
2.原理: 利用消息转发机制,将方法分发到多个对象中
使用方式:
self.tableView.delegate = AOProtocolDispatcher(UITableViewDelegate, self, self.delegateSource);
.h
#import <Foundation/Foundation.h>
#define AOProtocolDispatcher(__protocol__, ...) \
[ProtocolDispatcher dispatcherProtocol:@protocol(__protocol__) \
toImplemertors:[NSArray arrayWithObjects:__VA_ARGS__, nil]]
@interface ProtocolDispatcher : NSObject
+ (id)dispatcherProtocol:(Protocol *)protocol toImplemertors:(NSArray *)implemertors;
@end
.m
#import "ProtocolDispatcher.h"
#import <objc/runtime.h>
struct objc_method_description MethodDescriptionForSELInProtocol(Protocol *protocol, SEL sel) {
struct objc_method_description description = protocol_getMethodDescription(protocol, sel, YES, YES);
if (description.types) {
return description;
}
description = protocol_getMethodDescription(protocol, sel, NO, YES);
if (description.types) {
return description;
}
return (struct objc_method_description){NULL, NULL};
}
BOOL ProtocolContainSel(Protocol *protocol, SEL sel) {
return MethodDescriptionForSELInProtocol(protocol, sel).types ? YES: NO;
}
@interface ImplemertorContext : NSObject
@property (nonatomic, weak) id implemertor;
@end
@implementation ImplemertorContext
@end
@interface ProtocolDispatcher ()
@property (nonatomic, strong) Protocol *prococol;
@property (nonatomic, strong) NSArray *implemertors;
@end
@implementation ProtocolDispatcher
+ (id)dispatcherProtocol:(Protocol *)protocol toImplemertors:(NSArray *)implemertors {
return [[ProtocolDispatcher alloc] initWithProtocol:protocol toImplemertors:implemertors];
}
- (instancetype)initWithProtocol:(Protocol *)protocol toImplemertors:(NSArray *)implemertors {
if (self = [super init]) {
self.prococol = protocol;
NSMutableArray *implemertorContexts = [NSMutableArray arrayWithCapacity:implemertors.count];
[implemertors enumerateObjectsUsingBlock:^(id implemertor, NSUInteger idx, BOOL * _Nonnull stop) {
ImplemertorContext *implemertorContext = [ImplemertorContext new];
implemertorContext.implemertor = implemertor;
[implemertorContexts addObject:implemertorContext];
objc_setAssociatedObject(implemertor, _cmd, self, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}];
self.implemertors = implemertorContexts;
}
return self;
}
- (BOOL)respondsToSelector:(SEL)aSelector {
if (!ProtocolContainSel(self.prococol, aSelector)) {
return [super respondsToSelector:aSelector];
}
for (ImplemertorContext *implemertorContext in self.implemertors) {
if ([implemertorContext.implemertor respondsToSelector:aSelector]) {
return YES;
}
}
return NO;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
if (!ProtocolContainSel(self.prococol, aSelector)) {
return [super methodSignatureForSelector:aSelector];
}
struct objc_method_description methodDescription = MethodDescriptionForSELInProtocol(self.prococol, aSelector);
return [NSMethodSignature signatureWithObjCTypes:methodDescription.types];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
SEL aSelector = anInvocation.selector;
if (!ProtocolContainSel(self.prococol, aSelector)) {
[super forwardInvocation:anInvocation];
return;
}
for (ImplemertorContext *implemertorContext in self.implemertors) {
if ([implemertorContext.implemertor respondsToSelector:aSelector]) {
[anInvocation invokeWithTarget:implemertorContext.implemertor];
}
}
}
@end
转载于//www.cnblogs.com/daxueshan/p/11245748.html
还没有评论,来说两句吧...