FastElegantDelegation 1.0.1

FastElegantDelegation 1.0.1

测试已测试
语言语言 Objective C++Objective C++
许可证 MIT
发布最新发布2014 年 12 月

Yan Rabovik 维护。



  • Yan Rabovik

© 2013 Yan Rabovik (@rabovik 在推特上)

FastElegantDelegation 解决 3 个问题

  1. 优雅的单代理 无需烦人的 respondsToSelector: 检查;
  2. 实现 您自己的代码中的多代理模式;
  3. 为单个第三方源分配 多个代理

单代理

代理通常像这样实现

@protocol SomeDelegateProtocol <NSObject>
@optional
-(void)someOptionalDelegateMethod;
// ...
@end

@interface MyClass : NSObject
@property (nonatomic,weak) id<SomeDelegateProtocol> delegate;
@end

@implementation MyClass
-(void)someMethod{
    if ([self.delegate respondsToSelector:@selector(someOptionalDelegateMethod)]) {
        [self.delegate someOptionalDelegateMethod];
    }
}
// ...
@end

使用 FastElegantDelegation,您可以免除烦人的 respondsToSelector: 检查

@implementation MyClass
fed_use_proxy_for_delegate // just add this macro
-(void)someMethod{
    [self.delegate someOptionalDelegateMethod];
}
// ...
@end

它是如何工作的

  • fed_use_proxy_for_delegate 宏合成了 delegatesetDelegate 方法;
  • delegate 返回一个将消息转发到真实代理的 FEDProxy 类。如果代理没有对可选协议方法做出响应,代理就像消息被发送到 nil 一样什么也不做。

自定义代理名称

您可以为代理属性使用任何喜欢名称,但您应该在宏中指定获取者和设置者名称。

@interface MyClass : NSObject
@property (nonatomic,weak) id<SomeDelegateProtocol> myCoolDelegate;
@end

@implementation MyClass
fed_use_proxy_for_property(myCoolDelegate,setMyCoolDelegate)
// ...
@end

返回值

代理方法可以返回任何值。

@implementation MyClass
fed_use_proxy_for_delegate
-(void)someMethod{
    BOOL returnValue = [self.delegate methodReturningBOOL];
}
// ...
@end

安全性

如果将属性声明为 weak,则代理不会被保留。当代理析构时,代理也会自动析构。您将永远不会遇到代理由 self.delegate 返回但真实代理已经析构的情况。

FEDProxy 不破坏必需/可选范式。如果您尝试调用未在代理中实现的必需方法,您将获得异常。

强代理

如果您出于某种原因需要将代理声明为强类型,这没问题。FEDProxy 将会被强存储在 ivar 中,并保留真实代理。

@interface MyClass : NSObject
@property (nonatomic, strong) id<SomeDelegateProtocol> myStrongDelegate;
@end

性能

FEDProxy 使用快速消息转发(通过 forwardingTargetForSelector:)和缓存来防止多次内部 respondsToSelector: 检查。

在自己代码中使用多委托模式

使用 `fed_synthesize_multi_delegates` 宏,你可以在自己的类中实现多委托模式,这样你的类的客户端可以轻松地添加和移除委托。

示例

@class MyClass;
@protocol MyClassDelegate <NSObject>
-(void)myClassDidStartSomeJob;
@end

@interface MyClass : NSObject
-(void)addDelegate:(id<MyClassDelegate>)delegate;
-(void)removeDelegate:(id<MyClassDelegate>)delegate;
@end

@implementation MyClass
fed_synthesize_multi_delegates(MyClassDelegate)
-(void)someJob{
    [self.delegates myClassDidStartSomeJob]; // will be sent to each delegate
}
@end

fed_synthesize_multi_delegates 生成 `addDelegate:`、`removeDelegate:` 和 `delegates` 方法。

自定义方法名称

你可以根据自己的喜好命名方法。例如,你可以使用 `listener` 名称而不是 `delegate`。

@class MyClass;
@protocol MyClassListener <NSObject>
-(void)myClassDidStartSomeJob;
@end

@interface MyClass : NSObject
-(void)addListener:(id<MyClassListener>)delegate;
-(void)removeListener:(id<MyClassListener>)delegate;
@end

@implementation MyClass
fed_synthesize_multiproxy(MyClassListener, addListener, removeListener, listeners)
-(void)someJob{
    [self.listeners myClassDidStartSomeJob];
}
@end

返回值

如果方法返回值,则返回值将从响应选择器的列表中的第一个委托。

单个第三方资源的多委托

FEDMultiProxy 类是 NSProxy 的子类,它允许向单个第三方资源添加多个委托。

例如,你可以将多个委托分配给一个 `UIScrollView`。

__typeof(self) __weak weakSelf = self;
FEDMultiProxy *multiProxy = [FEDMultiProxy proxyWithDelegates:@[firstDelegate, secondDelegate]
                                                     protocol:@protocol(UIScrollViewDelegate)
                                          retainedByDelegates:YES
                                                    onDealloc:^{
                                                        weakSelf.scrollView.delegate = nil;
                                                    }];
self.scrollView.delegate = multiProxy;

你不需要保持对 `FEDMultiProxy` 对象的强引用。每个委托会自动保留它,当所有委托都无法访问时,它将被释放。此时将调用 `onDealloc` 块,你可以在那里将目标委托设置为 `nil`。

要求

许可

MIT 许可证。