CocoaPods trunk is moving to be read-only. Read more on the blog, there are 14 months to go.
| TestsTested | ✗ |
| LangLanguage | Objective C++Objective C++ |
| License | MIT |
| ReleasedLast Release | Dec 2014 |
Maintained by Yan Rabovik.
© 2013 Yan Rabovik (@rabovik on twitter)
FastElegantDelegation solves 3 problems:
respondsToSelector: checks;Delegation is often implemented like this:
@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];
}
}
// ...
@endWith FastElegantDelegation you may get rid of annoying respondsToSelector: checks:
@implementation MyClass
fed_use_proxy_for_delegate // just add this macro
-(void)someMethod{
[self.delegate someOptionalDelegateMethod];
}
// ...
@endfed_use_proxy_for_delegate macro synthesizes delegate and setDelegate methods;delegate returns a FEDProxy class that forwards messages to the real delegate. If delegate does not respond to an optional protocol method, proxy just does nothing like when the message is sent to nil.You may use any name you like for the delegate property, but you should specify getter and setter names in the macro:
@interface MyClass : NSObject
@property (nonatomic,weak) id<SomeDelegateProtocol> myCoolDelegate;
@end
@implementation MyClass
fed_use_proxy_for_property(myCoolDelegate,setMyCoolDelegate)
// ...
@endDelegate methods may return any value.
@implementation MyClass
fed_use_proxy_for_delegate
-(void)someMethod{
BOOL returnValue = [self.delegate methodReturningBOOL];
}
// ...
@endIf the property is declared as weak then delegate is not retained. When delegate deallocates, proxy is automatically deallocated too. You will never get into a situation when proxy returned by self.delegate is alive, but real delegate is already deallocated.
FEDProxy does not break required/optional paradigm. If you try to call required method that is not implemented in the delegate, you'll get an exception.
If for some reason you need to declare delegate as strong, it is OK. FEDProxy will be strongly stored in the ivar and will retain real delegate.
@interface MyClass : NSObject
@property (nonatomic, strong) id<SomeDelegateProtocol> myStrongDelegate;
@endFEDProxy uses fast message forwarding (via forwardingTargetForSelector:) and a cache to prevent multiple internal respondsToSelector: checks.
With fed_synthesize_multi_delegates macro you may implement multi-delegate pattern in your own class so that the clients of your class may easily add and remove delegates.
Example:
@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
}
@endfed_synthesize_multi_delegates synthesizes addDelegate:, removeDelegate: and delegates methods.
You can name methods as you like. For example you may use listener name instead of 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];
}
@endIf a method returns a value the return value will be from the first delegate in the list that responds to the selector.
FEDMultiProxy class is a NSProxy subclass that allows to add multiple delegates to a single third-party source.
For example, you may assign multiple delegates to a 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;You do not need to keep a strong reference to FEDMultiProxy object. It is automatically retained by each delegate and will be deallocated when all delegates die. onDealloc block will be called at that moment and you may set targets delegate to nil there.
MIT License.