1. 用途: 能够制定多个对象实现<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

Protocol协议分发器的更多相关文章

  1. iOS 协议分发

    Github:AOMultiproxier.HJProtocolDispatcher 协议实现分发器,能够轻易实现将协议事件分发给多个实现者. 一.AOMultiproxier.h #define A ...

  2. 开源负载均衡通讯分发器(LB dispatcher) - G5

    from:http://bbs.csdn.net/topics/390753043 1.开发背景今天和系统运维的老大聊天,谈到一直在用的F5,行里对其评价为价格过高.功能复杂难懂,反正印象不是很好,使 ...

  3. 实现 Redis 协议解析器

    本文是 <用 Golang 实现一个 Redis>系列文章第二篇,本文将分别介绍Redis 通信协议 以及 协议解析器 的实现,若您对协议有所了解可以直接阅读协议解析器部分. Redis ...

  4. SIP (Session Initiation Protocol) 协议

    Session Initiation Protocol 介绍 SIP是VoIP技术最常使用的协议,它是一种应用程序层协议,可与其他应用程序层协议配合使用,以控制Internet上的多媒体通信会话. V ...

  5. jQuery源码分析系列(33) : AJAX中的前置过滤器和请求分发器

    jQuery1.5以后,AJAX模块提供了三个新的方法用于管理.扩展AJAX请求,分别是: 1.前置过滤器 jQuery. ajaxPrefilter 2.请求分发器 jQuery. ajaxTran ...

  6. SpringMVC核心分发器DispatcherServlet分析[附带源码分析]

    目录 前言 DispatcherServlet初始化过程 DispatcherServlet处理请求过程 总结 参考资料 前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不 ...

  7. Objective-C( protocol协议)

    protocol 协议 protocol:用来声明方法 1.协议的定义 @protocol 协议名称 <NSObject> // 方法声明列表.... @end 2.如何遵守协议 1> ...

  8. ISO 基础之 (十三) protocol 协议

    一 简绍 protocol,简单来说就是一系列不属于任何类的方法列表,其中声明的方法可以被任何类实现.这种模式一般称为代理(delegation)模式.通过Protocol定义各种行为,在不同的场景采 ...

  9. 【转】iOS开发-Protocol协议及委托代理(Delegate)传值

    原文网址:http://www.cnblogs.com/GarveyCalvin/p/4210828.html 前言:因为Object-C是不支持多继承的,所以很多时候都是用Protocol(协议)来 ...

随机推荐

  1. SQL常用语句之数据库的创建、删除以及属性的修改-篇幅1

    本篇文章主要总结了SQL Server 语句的使用和一些基础知识,因为目前我也正在学习,所以总结一下. 要使用数据库语句,首先就要知道数据库对象的结构: 通常情况下,如果不会引起混淆,可以直接使用对象 ...

  2. MySQL基础(创建库,创建表,添加数据)

    CREATE DATABASE 数据库名; CREATE TABLE student2(sno VARCHAR(20) NOT NULL PRIMARY KEY COMMENT"学号&quo ...

  3. Spring数据库连接池 c3p0、dbcp、spring-jdbc

    在用dbcp的时候 后面加上 destroy-method="close" 销毁的方法没事 但是用 spring的jdbc就会报错 提示找不到close这个方法  这是为什么? D ...

  4. Qt 如何使用反射?

    Qt 如何使用反射? c++ 反射 标准库暂时还没有,那我们来看看如何使用 qt 来进行反射. 反射类的案例 1. 通过注册的类型需找 id 进行实例化该类 myclass.h #include &l ...

  5. 使用再生龙对ubuntu16.04系统完全备份与还原

    1.制作再生龙U盘启动 1.所需要的软件 1.clonezilla-live-2.5.5-38-amd64.iso(再生龙系统镜像) 2.UltraISO(镜像刻录软件) 3.两个空白U盘(U盘A-用 ...

  6. Windows程序设计--(一)起步

    1.3 你的第一个Windows程序 1.3.2 Windows 对应程序 #include <windows.h> int WINAPI WinMain(HINSTANCE hInsta ...

  7. XMPP即时通讯协议使用(五)——搭建简单的Openfire插件

    前言 在开发Openfire插件前需要构建完成服务器源码编辑环境,具体操作步骤请参照Openfire服务器源码编译的了解. 开发简单的Openfire插件 1.已构建完成的Openfire源码结构如下 ...

  8. smbtar - 直接备份SMB/CIFS共享资源到UNIX磁带设备的shell脚本

    总览 smbtar -s server [-p password] [-x service] [-X] [-d directory] [-u user] [-t tape] [-b blocksize ...

  9. vue,一路走来(6)--微信支付

    微信支付 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6 分享一下vue实现微信支付.在微信浏览器里面 ...

  10. OkHttp源码剥离导入到eclipse中

    1.里面有两个类关于Android版本的我稍微修改过了,没有用的. 2.可以直接导入eclipse中,maven里面的jar包可能还有不需要的冗余,可以自己去剔除. https://github.co ...