8

I have a C++ class that I recently renamed from *.cpp to *.mm to support objective-c. So I can add the following objective-c code.

[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(notificationHandler:) 
                                                 name:@"notify"
                                               object:nil];
  • How do/Can I write the notificationHandler method in c++?
  • Will setting addObserver:self property work?
peterh
  • 11,875
  • 18
  • 85
  • 108
valmo
  • 1,156
  • 2
  • 12
  • 22

3 Answers3

18

Or you could also just use blocks and do:

[
    [NSNotificationCenter defaultCenter] addObserverForName: @"notify"
    object: nil
    queue: nil
    usingBlock: ^ (NSNotification * note) {
        // do stuff here, like calling a C++ method
    }
];
Mathew Kurian
  • 5,949
  • 5
  • 46
  • 73
Remy Bardou
  • 189
  • 1
  • 2
16

You'd need an Objective-C class to handle Objective-C notifications. Core Foundation to the rescue!

In.. wherever you start listening for notifications, e.g. your constructor:

static void notificationHandler(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo);

MyClass::MyClass() : {
    // do other setup ...

    CFNotificationCenterAddObserver
    (
        CFNotificationCenterGetLocalCenter(),
        this,
        &notificationHandler,
        CFSTR("notify"),
        NULL,
        CFNotificationSuspensionBehaviorDeliverImmediately
    );
}

When done, e.g. in your destructor:

MyClass::~MyClass() {
    CFNotificationCenterRemoveEveryObserver
    (
        CFNotificationCenterGetLocalCenter(),
        this
    );
}

And finally, a static function to handle the dispatch:

static void notificationHandler(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
    (static_cast<MyClass *>(observer))->reallyHandleTheNotification();
}

Ta da!

Jonathan Grynspan
  • 43,286
  • 8
  • 74
  • 104
  • Oh cool. I was wondering what this core foundation thing was about. thanks mate – valmo May 19 '11 at 17:35
  • impressive. would these CF* functions be considered "toll free bridge" to the "normal" NSNotificationCenter? – johnbakers Apr 10 '13 at 12:30
  • No, `CFNotificationCenter` is not toll-free bridged with `NSNotificationCenter`. So a custom instance of either will not be usable in the other API. However, if you use a standard center in either (e.g. `CFNotificationCenterGetLocalCenter()` or `[NSNotificationCenter defaultCenter]`) and post a notification to it, the notification is posted to both sets of listeners (i.e. the interfaces are distinct, but the underlying system is the same.) – Jonathan Grynspan Apr 11 '13 at 22:39
4

You can't add a C++ method as an observer because of how Objective-C method handles method invocation vs C++. You must have an Objective-C class (Declared with @interface Class .. @end) to respond to those methods.

Your only option is to wrap your C++ class in an Objective-C class, or just have a very light wrapper that just has a reference to an object and calls a method statically once the notification arrives.

yan
  • 20,644
  • 3
  • 38
  • 48
  • :( I was afraid the answer was going to be something like that. Thanks for the response – valmo May 19 '11 at 17:23