126

How to perform call back functions in Objective-C?

I would just like to see some completed examples and I should understand it.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
ReachConnection
  • 1,831
  • 6
  • 22
  • 32

5 Answers5

143

For completeness, since StackOverflow RSS just randomly resurrected the question for me, the other (newer) option is to use blocks:

@interface MyClass: NSObject
{
    void (^_completionHandler)(int someParameter);
}

- (void) doSomethingWithCompletionHandler:(void(^)(int))handler;
@end


@implementation MyClass

- (void) doSomethingWithCompletionHandler:(void(^)(int))handler
{
    // NOTE: copying is very important if you'll call the callback asynchronously,
    // even with garbage collection!
    _completionHandler = [handler copy];

    // Do stuff, possibly asynchronously...
    int result = 5 + 3;

    // Call completion handler.
    _completionHandler(result);

    // Clean up.
    [_completionHandler release];
    _completionHandler = nil;
}

@end

...

MyClass *foo = [[MyClass alloc] init];
int x = 2;
[foo doSomethingWithCompletionHandler:^(int result){
    // Prints 10
    NSLog(@"%i", x + result);
}];
Jens Ayton
  • 14,532
  • 3
  • 33
  • 47
96

Normally, callbacks in objective C are done with delegates. Here's an example of a custom delegate implementation;


Header File:

@interface MyClass : NSObject {
    id delegate;
}
- (void)setDelegate:(id)delegate;
- (void)doSomething;
@end

@interface NSObject(MyDelegateMethods)
- (void)myClassWillDoSomething:(MyClass *)myClass;
- (void)myClassDidDoSomething:(MyClass *)myClass;
@end

Implementation (.m) File

@implementation MyClass
- (void)setDelegate:(id)aDelegate {
    delegate = aDelegate; /// Not retained
}

- (void)doSomething {
    [delegate myClassWillDoSomething:self];
    /* DO SOMETHING */
    [delegate myClassDidDoSomething:self];
}
@end

That illustrates the general approach. You make a category on NSObject that declares the names of your callback methods. NSObject doesn't actually implement these methods. This type of category is called an informal protocol, you're just saying that many objects might implement these methods. They're a way to forward declare the type signature of the selector.

Next you have some object be the delegate of "MyClass" and MyClass calls the delegate methods on the delegate as appropriate. If your delegate callbacks are optional, you'll typically guard them at the dispatch site with something like "if ([delegate respondsToSelector:@selector(myClassWillDoSomething:)) {". In my example, the delegate is required to implement both methods.

Instead of an informal protocol, you can also use a formal protocol defined with @protocol. If you do that, you'd change the type of the delegate setter, and instance variable to be "id <MyClassDelegate>" instead of just "id".

Also, you'll notice the delegate is not retained. This is typically done because the object that "owns" instances of "MyClass" is typically also the delegate. If MyClass retained its delegate, then there would be a retain cycle. It's a good idea in the dealloc method of a class that that has a MyClass instance and is its delegate to clear that delegate reference since it's a weak back pointer. Otherwise if something is keeping the MyClass instance alive, you'll have a dangling pointer.

Jon Hess
  • 14,237
  • 1
  • 47
  • 51
  • 1
    +1 Good thorough answer. Icing on the cake would be a link to more in-depth Apple documentation on delegates. :-) – Quinn Taylor Jun 19 '09 at 01:44
  • Jon, thanks a lot of for your help. I really appreciate your help. I am sorry about this, but I am not too clear on the answer. Message .m is a class that set itself as the delegate during doSomething function call. Is doSomething the callback function that the user calls? since I am under the impression that the user calls doSomething, and your call back functions are myClassWillDoSomethingg & myClassDidDoSomething. As well, can you show me how to create a higher class that calls the call back function. I am a C programmer so I am not too familiar with the Obj-C environment as of yet. – ReachConnection Jun 19 '09 at 19:24
  • "Message .m" just meant, in you're .m file. You'd have a separate class, let's call it "Foo". Foo would have a "MyClass *myClass" variable, and at some point Foo would say "[myClass setDelegate:self]". At any point after that, if anyone including foo invoked the doSomethingMethod on that instance of MyClass, foo would have its myClassWillDoSomething, and myClassDidDoSomething methods invoked. I'll actually also just post a second different example that doesn't use delegates. – Jon Hess Jun 19 '09 at 21:19
  • I don't think the .m stands for "message". – Chuck Jun 19 '09 at 21:40
  • Interesting, I'd always thought of it as message, but on the web it looks like people are either saying it's "Method" or "implementation". – Jon Hess Jun 19 '09 at 23:26
  • 1
    http://stackoverflow.com/questions/652186/why-do-objective-c-files-use-the-m-extension – ptomli Oct 12 '10 at 14:36
  • I did it for my objective-c class, how can I use it in swift to get callbacks from objective-c? – user924 Mar 14 '18 at 14:10
53

Here's an example that keeps the concepts of delegates out, and just does a raw call back.

@interface Foo : NSObject {
}
- (void)doSomethingAndNotifyObject:(id)object withSelector:(SEL)selector;
@end

@interface Bar : NSObject {
}
@end

@implementation Foo
- (void)doSomethingAndNotifyObject:(id)object withSelector:(SEL)selector {
    /* do lots of stuff */
    [object performSelector:selector withObject:self];
}
@end

@implementation Bar
- (void)aMethod {
    Foo *foo = [[[Foo alloc] init] autorelease];
    [foo doSomethingAndNotifyObject:self withSelector:@selector(fooIsDone:)];
}

- (void)fooIsDone:(id)sender {
    NSLog(@"Foo Is Done!");
}
@end

Typically the method -[Foo doSomethingAndNotifyObject:withSelector:] would be asynchronous which would make the callback more useful than it is here.

Jon Hess
  • 14,237
  • 1
  • 47
  • 51
  • 1
    Thanks a lot John. I understand your first callback implementation after your comments. As well, your 2nd callback implementation is more straightforward. Both are very good. – ReachConnection Jun 22 '09 at 20:36
  • 1
    Thanks for posting this Jon, it was very helpful. I had to change [object performSelectorwithObject:self]; to [object performSelector:selector withObject:self]; in order to get it to work correctly. – Banjer Oct 12 '10 at 01:48
18

To keep this question up-to-date, iOS 5.0's introduction of ARC means this can be achieved using Blocks even more concisely:

@interface Robot: NSObject
+ (void)sayHi:(void(^)(NSString *))callback;
@end

@implementation Robot
+ (void)sayHi:(void(^)(NSString *))callback {
    // Return a message to the callback
    callback(@"Hello to you too!");
}
@end

[Robot sayHi:^(NSString *reply){
  NSLog(@"%@", reply);
}];

There's always F****ng Block Syntax if you ever forget Objective-C's Block syntax.

Ryan Brodie
  • 6,554
  • 8
  • 40
  • 57
  • In @interface should be `+ (void)sayHi:(void(^)(NSString *reply))callback;` not `+ (void)sayHi:(void(^)(NSString *))callback;` – Tim007 Mar 31 '16 at 11:48
  • Not according to aforementioned [F****ng Block Syntax](http://goshdarnblocksyntax.com/): `- (void)someMethodThatTakesABlock:(returnType (^nullability)(parameterTypes))blockName;` (Note `parameterTypes` not `parameters`) – Ryan Brodie Mar 31 '16 at 12:13
5

CallBack: There are 4 types of callback in Objective C

  1. Selector type : You can see NSTimer,UIPangesture are the examples of Selector callback. Used for very limited execution of code.

  2. Delegate Type : Common and most used in Apple framework. UITableViewDelegate, NSNURLConnectionDelegate. They are usually used to show Downloading many images from server asynchronously etc.

  3. NSNotifications : NotificationCenter is one of features of Objective C which used to notify many receiptants at time when event occur.
  4. Blocks : Blocks are more commonly used in Objective C programming. It is great feature and used for executing chunk of code. You can also refer tutorial to understand : Blocks tutorial

Please let me if any other answer for it. I will appreciate it.

Anil Gupta
  • 1,155
  • 1
  • 19
  • 26