user287354
user287354

Reputation: 21

NSNotificationCenter selector won't work with its NSNotification

I'm working on a Cocoa project with some C in it (I know, objc contains C...) and am trying to understand NSNotificationCenters. Here's the situation:

I have a struct declared as typedef struct {/*code here*/} structName;

In my - (id)init method, I have

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(selName:) name:@"notName" object:nil];

I have a callback function:

int callback(/*args*/) {
    structName *f = ...
    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"notName" object:[[NSValue valueWithPointer:f] retain]];
    [autoreleasepool release];
}

And then for my selector:

- (void)selName:(NSNotification *)note
{
    NSLog(@"here");
    NSLog(@"note is %@", note);
}

Now, if I comment out that second NSLog, everything seems to work (i.e. "here" is printed). But if I leave it in, nothing about the NSNotification seems to work. But this seems to defeat the purpose of the object, userInfo, etc. of the NSNotification.

What am I doing wrong and how can I fix it so I can have access to my structName f?

@Nathan Okay, so now I have

NSDictionary *dict = [NSDictionary dictionaryWithObject:[NSValue valueWithPointer:f] forKey:@"fkey"];//f, not &f. I had a typo in the OP which I fixed.
[[NSNotificationCenter defaultCenter] postNotificationName:@"notName" object:nil userInfo:[dict retain]];

...but the problem remains. Any chance this has to do with the typo I fixed?

Edit:

The problem continues even with changing the two lines above to

[[NSNotificationCenter defaultCenter] postNotificationName:@"notName" object:nil userInfo:[NSDictionary dictionaryWithObject:[NSData dataWithBytes:f length:sizeof(structName)] forKey:@"fkey"]];

Upvotes: 2

Views: 7687

Answers (5)

Sanket
Sanket

Reputation: 307

Instead, you can use the following:

- (void)selName:(NSNotification *)note
{
    NSLog(@"here");
    NSLog(@"note is %@", [note userInfo]);
}

Upvotes: 0

progrmr
progrmr

Reputation: 77191

You said it worked if you comment out the second NSLog. And that second NSLog appears to be incorrect:

- (void)selName:(NSNotification *)note
{
    NSLog(@"here");
    NSLog(@"note is %@", note);   
}

%@ format is to print an NSString but "note" is not a NSString, it's an NSNotification object. NSNotification has a name attribute that returns an NSString. Try changing the second NSLog to this:

NSLog(@"note is %@", [note name]);

Upvotes: 0

diederikh
diederikh

Reputation: 25271

NSValue needs a pointer to your struct, not the struct itself:

[NSValue valueWithPointer:&f]

Upvotes: 0

Nathan Kinsinger
Nathan Kinsinger

Reputation: 25021

You should be using +notificationWithName:object:userInfo: not +notificationWithName:object:.

The object parameter is the object sending the notification. Normally this would be self for an object posting the notification but since your calling this from a C function it should be nil.

The userInfo parameter is an NSDictionary so add the NSValue to a dictionary and send that.

Then in your selName: method get the -userInfo dict from the NSNotification and pull your info out from there.

Note: You are creating a leak by retaining the NSValue when you shouldn't.

Edit:

How long does the struct exist? NSValue will not copy the contents of the pointer so maybe it's being deallocated? Try using NSData's dataWithBytes:length: instead.

Also make sure to check the console for runtime errors (in Xcode:Run > Console).

And you do not need to retain dict. You may want to (re)read the Cocoa memory management docs.

Upvotes: 1

Peter Hosey
Peter Hosey

Reputation: 96333

Works for me. What are you doing differently?

Upvotes: 1

Related Questions