Skip to content

Callback handlers using selectors

sebastienwindal edited this page Dec 6, 2012 · 14 revisions

This method uses NSInvocation to store callback methods registered with the object you want to be notified from. From apple documentation:

An NSInvocation is an Objective-C message rendered static, that is, it is an action turned into an object. NSInvocation objects are used to store and forward messages between objects and between applications.

With this method you just have to provide for a way to register for actions/callbacks, store registered callbacks in your own array(s), and loop through callbacks when you want to notify subscribers

In this example, I have provided two methods to register for actions:

-(void) addCalculationProgressHandlerForTarget:(id)obj selector:(SEL)handler;
-(void) addCalculationResultHandlerForTarget:(id)obj selector:(SEL)handler;

and two private arrays to store NSInvocation objects:

@property (nonatomic, strong) NSMutableArray *progressHandlers; // array of NSInvocation
@property (nonatomic, strong) NSMutableArray *completionHandlers; // array of NSInvocation

While it is relatively complex to implement, it is very simple to consume:

notes

This pattern could almost be interchanged with delegation except multiple objects can register with the observed object. This patterns works very well with any kind of child->parent communication such as View->View controller (the typical action workflow, for buttons, etc...).

Pros

  • very easy to consume
  • You have more control since you implement the notification system, you just use NSNotification to hold CB information and you can customize it to your needs.
  • multiple callbacks possible

Cons

  • More work on the notifier side, again you have to do the work.
  • A selector can only have one argument?
  • no easy way to unregister from an action, again you have to implement it.

Gotchas and best practices

Consider using blocks instead of NSInvocation/selectors

If you like this pattern, consider the next one! It is very similar except blocks are easier to work with and more flexible than selector/NSInvocation objects. Blocks were introduces fairly recently in iOS.

Switch to main thread if needed!

The callback may not be called in the main thread.

Examples in Cocoa

  • UIControl that support actions (e.g. UIButton, UISwitch, etc...)
[myButton addTarget:self action:@selector(buttonTappedAction:) forControlEvents:UIControlEventTouchUpInside];

Also note that when you hook up a button action in Interface builder to an IBAction, it is what it is doing under the hood.

  • Gesture recognizer action
[myPinchGesture addTarget:self action:@selector(viewWasPinched:)]
  • etc...

Back

Clone this wiki locally