I understand that UI controls such as UITextField notify of client interactions / events via their delegate, which is defined as a class that supports the required protocol.
I have often found myself wanting to receive notifications of UI event in more than one class, so would want to support multicasting. For example, specifying more than one delegate for a UI control. I am pretty sure that there is no iOS framework feature that supports this. I was wondering if anyone had come up with a decent solution to this problem?
There is a cocoa feature that lets you build multicast delegates with relative ease - it's the Message Forwarding system built into the framework.
Make a class that overrides
forwardInvocation:
, and return an instance of your object instead of a delegate. This is what is sometimes called a "Trampoline object". The logic inside yourforwardInvocation:
implementation can now decide which "real" objects should receive the message, and forward the invocation to one or more of them.As an update to this accepted answer, I created my own multicasting delegate implementation here:
http://www.scottlogic.co.uk/blog/colin/2012/11/a-multicast-delegate-pattern-for-ios-controls/
One technique to support multicasting is to give your delegating class the following methods:
@interface Delegator : NSObject - (void)addDelegate:(id<MyProtocol>)delegate; - (void)removeDelegate:(id<MyProtocol>)delegate; @end
And store the reference to the delegates in an
NSHashTable
.See the implementation here: http://arielelkin.github.io/articles/objective-c-multicast-delegate/
You could implement your UI control in your class, and then your class will receive notification from this UI, you can send message to another class (using the same delegate technic - implement delegate property in first class, and then in second class implement delegate method from 1-st class). For example, for UITextField method -textFieldDidEndEditing:
In first class -
1) implement protocol:
2)
@property (nonatomic, unsafe_unretained, readwrite) id <TextControllerDelegate> delegate;
3)in method -
(void)textFieldDidEndEditing:(UITextField *)textField
inside the class, call[delegate textFieldDidEndEditing:textField]
In second class:
1) implement object of first class, set delegate to self (to second class).
2) implement method -
(void)textFieldDidEndEditing:(UITextField *)textField