ILABMultiDelegate 0.0.7

ILABMultiDelegate 0.0.7

测试已测试
Lang语言 Obj-CObjective C
许可证 MIT
Published最后发布2017年5月

Jon Gilkison维护。



  • Jon Gilkison

这非常依赖于Alejandro Isaza的 MultiDelegate

MultiDelegate 是 Objective-C 中的一个代理多路复用类。换句话说,它将代理方法分发给多个对象,而不是被限制在一个代理对象上。您还可以将其用作一个通用方法分派机制。更多信息请见博客文章

与预现有类(UIScrollView、UITableView 等)一起使用

假设你有一个 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,对包含 ABC(按此顺序)的 ILABMultiDelegate 调用 getInt 将返回 1
  • ILABMultiDelegate 不保留添加到其中的对象的强引用。
  • 一些对象仅在第一次设置代理时调用 respondsToSelector: 以提高性能,因此请确保在设置它为代理之前将所有代理添加到 ILABMultiDelegate 中。

安装

如果您使用 CocoaPods,将其添加到您的 Podfile

pod 'ILABMultiDelegate'

否则,将 ILABMultiDelegate.h/.m 添加到您的项目中。

特别感谢

当然,特别感谢 Alejandro Isaza 编写了 MultiDelegate,这是从该代码中提取了 80% 的。