这非常依赖于Alejandro Isaza的 MultiDelegate。
MultiDelegate 是 Objective-C 中的一个代理多路复用类。换句话说,它将代理方法分发给多个对象,而不是被限制在一个代理对象上。您还可以将其用作一个通用方法分派机制。更多信息请见博客文章。
假设你有一个 UITableView
,你想要使用两个分离的类来实现数据源:一个是实际数据源,用于实现 tableView:numberOfRowsInSection:
方法,另一个是单元格工厂,用于实现 tableView:cellForRowAtIndexPath:
方法以构建单元格。
首先创建一个 ILABMultiDelegate
实例。您需要一个强壮的引用来引用此实例,因为大多数对象不会保留其代理
_multiDelegate = [ILABMultiDelegate delegateWithProtocol:@protocol(UITableViewDataSource)];
然后向 _multiDelegate 对象添加所有实际代理
[_multiDelegate addDelegate:self];
[_multiDelegate addDelegate:_dataSource];
最后将表格的数据源设置为代理多路复用器
self.tableView.dataSource = (id)_multiDelegate;
如果您正在编写一个类,并且希望它具有多代理支持,那就很容易添加。以下是一个具有多代理支持的类的头文件
#import "ILABMultiDelegate.h"
@protocol ILABYourClassDelegate;
@interface ILABYourClass : NSObject
@property (readonly) id<ILABMultiDelegateProtocol, ILABYourClassDelegate> delegate;
-(void)doSomething;
@end
@protocol ILABDelegateObjectDelegate<NSObject>
-(void)didSomething;
@end
您会注意到我们的 delegate
属性是 readonly
。这是因为您的代理实际上是一个 ILABMultiDelegate
实例。因为它标记了 ILABMultiDelegateProtocol
,您可以使用 addDelegate:
和 insertDelegate:
方法实际添加您的代理。
然后您的实现将看起来像这样
@implementation ILABYourClass
-(instancetype)init
{
if ((self=[super init]))
{
_delegate=[ILABMultiDelegate delegateWithProtocol:@protocol(ILABDelegateObjectDelegate)];
}
return self;
}
-(void)doSomething
{
[_delegate didSomething];
}
这里我们创建了一个 ILABMultiDelegate
实例,并分配给我们的 _delegate ivar。注意我们如何将委托的协议传递给构造函数?我们这样做是为了确保将来添加的任何委托都符合协议。
要添加一个代理,您的客户端类会这样做
ILABYourClass *myClass=[ILABYourClass new];
[myClass.delegate addDelegate:self];
允许您指定 ILABMultiDelegate
将处理多个协议。在严格模式下,添加到 ILABMultiDelegate
实例的任何代理都必须实现 所有 的协议,否则将引发异常。
在不严格模式下,每个添加的代理可以实现对 ILABMultiDelegate
处理的任何协议中的一个或多个而不引发异常。
例如,假设我们有以下三个协议定义
@protocol ProtocolA <NSObject>
-(void)selector_1;
@end
@protocol ProtocolB <NSObject>
-(void)selector_2;
@end
@protocol ProtocolC <NSObject>
-(void)selector_3;
@end
现在我们有两个类,它们将作为代理,实现这些协议
@interface DelegateAB : NSObject<ProtocolA, ProtocolB>
@end
@interface DelegateC : NSObject<ProtocolC>
@end
我们的类定义
@interface OurObject : NSObject
@property (readonly) id<ILABMultiDelegateProtocol, ProtocolA, ProtocolB, ProtocolC> delegate;
@end
本类的初始化器
@implementation OurObject
-(instancetype)init {
if ((self = [super init])) {
_delegate = [ILABMultiDelegate delegateWithProtocols:@[@protocol(ProtocolA),@protocol(ProtocolB),@protocol(ProtocolC)] strict:NO];
}
return self;
}
@end
在我们的初始化器中,我们创建了一个新的 ILABMultiDelegate
实例,传递了代理应该实现的协议列表。请注意,向 strict:
传递 NO
告诉 ILABMultiDelegate
添加的任何代理只需要符合一个或多个协议。如果我们将 YES
传递给它,那么每个添加的代理都需要符合 所有 协议。
A
通过返回 1
实现方法 getInt
,对象 B
通过返回 2
实现方法 getInt
,而对象 C
没有实现 getInt
,对包含 A
、B
和 C
(按此顺序)的 ILABMultiDelegate
调用 getInt
将返回 1
。ILABMultiDelegate
不保留添加到其中的对象的强引用。respondsToSelector:
以提高性能,因此请确保在设置它为代理之前将所有代理添加到 ILABMultiDelegate
中。如果您使用 CocoaPods,将其添加到您的 Podfile
pod 'ILABMultiDelegate'
否则,将 ILABMultiDelegate.h/.m
添加到您的项目中。
当然,特别感谢 Alejandro Isaza 编写了 MultiDelegate,这是从该代码中提取了 80% 的。