Multicast Delegates
Pattern for adding multicasting capabilities to existing iOS controls. Adding multicasting allows for improved clarity and code re-use.
Multicast delegates for any controls
Section titled “Multicast delegates for any controls”Forward messages one object to another by delegates, multicasting these messages to multiple observers..
Step 1:- Create NSObject class of RRMulticastDelegate
Step 2:- Following code implement in RRMulticastDelegate.h file
#import <Foundation/Foundation.h>
@interface RRMulticastDelegate : NSObject
{ //Handle multiple observers of delegate NSMutableArray* _delegates;}
// Delegate method implementation to the list of observers- (void)addDelegate:(id)delegate;- (void)removeDelegate:(id)delegate;
// Get multiple delegates-(NSArray *)delegatesObjects;
@endStep 3:- Following code implement in RRMulticastDelegate.m file
#import "RRMulticastDelegate.h"
@implementation RRMulticastDelegate
- (id)init{ if (self = [super init]) { _delegates = [NSMutableArray array]; } return self;}
-(NSArray *)delegatesObjects{ return _delegates;}
- (void)removeDelegate:(id)delegate{ if ([_delegates containsObject:delegate]) [_delegates removeObject:delegate];}
- (void)addDelegate:(id)delegate{ if (![_delegates containsObject:delegate]) [_delegates addObject:delegate];}
- (BOOL)respondsToSelector:(SEL)aSelector{ if ([super respondsToSelector:aSelector]) return YES;
// if any of the delegates respond to this selector, return YES for(id delegate in _delegates) { if (!delegate) continue;
if ([delegate respondsToSelector:aSelector]) { return YES; } } return NO;}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{ // can this class create the sinature? NSMethodSignature* signature = [super methodSignatureForSelector:aSelector];
// if not, try our delegates if (!signature) { for(id delegate in _delegates) { if (!delegate) continue;
if ([delegate respondsToSelector:aSelector]) { return [delegate methodSignatureForSelector:aSelector]; } } } return signature;}
- (void)forwardInvocation:(NSInvocation *)anInvocation{ // forward the invocation to every delegate for(id delegate in _delegates) { if (!delegate) continue;
if ([delegate respondsToSelector:[anInvocation selector]]) { [anInvocation invokeWithTarget:delegate]; } }}
@endStep 4:- Create NSObject category class of RRProperty
Step 5:- Following code implement in NSObject+RRProperty.h file
#import <Foundation/Foundation.h>
#import "RRMulticastDelegate.h"
@interface NSObject (RRProperty)<UITextFieldDelegate,UITableViewDataSource>
-(void)setObject:(id)block forKey:(NSString *)key;-(id)objectForKey:(NSString *)key;
#pragma mark - Multicast Delegate
- (RRMulticastDelegate *)multicastDelegate;- (RRMulticastDelegate *)multicastDatasource;
-(void)addDelegate:(id)delegate;-(void)addDataSource:(id)datasource;
@endStep 6:- Following code implement in NSObject+RRProperty.m file
#import "NSObject+RRProperty.h"
#import <objc/message.h>#import <objc/runtime.h>
#pragma GCC diagnostic ignored "-Wprotocol"
static NSString *const MULTICASTDELEGATE = @"MULTICASTDELEGATE";static NSString *const MULTICASTDATASOURCE = @"MULTICASTDATASOURCE";
@implementation NSObject (RRProperty)
-(void)setObject:(id)block forKey:(NSString *)key{ objc_setAssociatedObject(self, (__bridge const void *)(key), block, OBJC_ASSOCIATION_RETAIN);}
-(id)objectForKey:(NSString *)key{ return objc_getAssociatedObject(self, (__bridge const void *)(key));}
#pragma mark - Multicast Delegate
- (RRMulticastDelegate *)multicastDelegate{ id multicastDelegate = [self objectForKey:MULTICASTDELEGATE]; if (multicastDelegate == nil) { multicastDelegate = [[RRMulticastDelegate alloc] init];
[self setObject:multicastDelegate forKey:MULTICASTDELEGATE]; }
return multicastDelegate;}
- (RRMulticastDelegate *)multicastDatasource{ id multicastDatasource = [self objectForKey:MULTICASTDATASOURCE]; if (multicastDatasource == nil) { multicastDatasource = [[RRMulticastDelegate alloc] init];
[self setObject:multicastDatasource forKey:MULTICASTDATASOURCE]; }
return multicastDatasource;}
-(void)addDelegate:(id)delegate{ [self.multicastDelegate addDelegate:delegate];
UITextField *text = (UITextField *) self; text.delegate = self.multicastDelegate;}
-(void)addDataSource:(id)datasource{ [self.multicastDatasource addDelegate:datasource]; UITableView *text = (UITableView *) self; text.dataSource = self.multicastDatasource;}
@endFinally you ca use multicast dalegate for any controls…
For ex…
Import your viewcontroller class in NSObject+RRProperty.h file to access its methods to set multicast delegate/datasource.
UITextView *txtView = [[UITextView alloc]initWithFrame:txtframe];[txtView addDelegate:self];
UITableView *tblView = [[UITableView alloc]initWithFrame:tblframe];[tblView addDelegate:self];[tblView addDataSource:self];