Does the NSNotification retain the object?
Asked Answered
C

2

21

My question is in regards the object that gets added to a -postNotificationName:object: userInfo: method.

Does the NSNotification retain the object ? (in a similar fashion to NSMutableDictionary or Array) ... meaning I can release the object after posting the notification

Below is a code snippet to help describe my question ... is it valid to release the object. A link to Apple documentation could be really helpful.

NSMutableDictionary *teamDictCopy = [self.teamDict mutableCopy];
[teamDictCopy setObject:[NSNumber numberWithInt:self.scrollViewIndex] forKey:@"imageIndex"];

if([self.statusButton.title isEqualToString:@"Completed"]){
    [[NSNotificationCenter defaultCenter] postNotificationName:@"UnComplete" object:teamDictCopy userInfo:nil];
}

[teamDictCopy release];
Czarra answered 17/3, 2011 at 21:50 Comment(0)
K
31

"Does the NSNotification retain the object ? (in a similar fashion to NSMutableDictionary or Array) ... meaning I can release the object after posting the notification"

I'm not sure if the object and userInfo parameters are retained by that method or not, but in practice, it shouldn't really matter.

I think you may be envisioning that NSNotificationCenter is creating these notifications and broadcasting them in an asynchronous manner, but that isn't the case. As stated in the documentation for NSNotificationCenter (see NSNotificationCenter Class Reference), notifications are posted synchronously:

A notification center delivers notifications to observers synchronously. In other words, the postNotification: methods do not return until all observers have received and processed the notification. To send notifications asynchronously use NSNotificationQueue. In a multithreaded application, notifications are always delivered in the thread in which the notification was posted, which may not be the same thread in which an observer registered itself.

So, in your code, the notification center creates the notification and then broadcasts it through the default center. Any objects which have registered for this combination of notification name and object will receive the notification and then perform the selector they specified when they registered for that notification. Afterwards, the control returns to the class that posted the notification.

In other words, by the time your code gets to the [teamDictCopy release] line, the teamDictCopy will already have been "used" by all of the interested parties. So, there shouldn't be any danger in releasing it.

Just a note on conventions. Generally, the object: parameter is meant to be the object that is posting the notification, and the userInfo: parameter is meant for an NSDictionary of extra information. So, normally, you would handle the notification like follows:

NSMutableDictionary *teamDictCopy = [self.teamDict mutableCopy];
[teamDictCopy setObject:
   [NSNumber numberWithInt:self.scrollViewIndex] forKey:@"imageIndex"];

if([self.statusButton.title isEqualToString:@"Completed"]){
 [[NSNotificationCenter defaultCenter] postNotificationName:@"UnComplete" 
     object:self userInfo:teamDictCopy];
    }

[teamDictCopy release];
Kingdon answered 18/3, 2011 at 2:49 Comment(2)
Thank you ... your answer cleared up more than my question asked. always learningCzarra
This would be true if NSNotifications were only used with NSNotificationCenters. What about NSNotificationQueue? In that case we're posting asynchronously and it does matter whether object is retained or not.Shoop
C
5

yes - you can release the object once it's been set as the notification's object.

you can also subclass.

as far as a specific document/statement: i don't remember one, specifically.

this is however the basis of objects, their instance variables, and distributed communications and signaling when types are identified as being an object.

i've written a test for you, so you can be assured of this. the use cases of notifications would be few if the object were not retained. just add a breakpoint where instructed, then run with breakpoints enabled. enjoy!

#import <Foundation/Foundation.h>

@interface MONObject : NSObject
@end

@implementation MONObject

- (id)retain {
    return self; /* << add breakpoint here */
}

/* needed to counter retain override
   (although all MONObjects will leak in this example)
*/
- (void)release {
}

@end

int main(int argc, const char* argv[]) {
    NSAutoreleasePool * pool = [NSAutoreleasePool new];

    NSString * name = @"UnComplete";
    MONObject * obj = [MONObject new];
    [[NSNotificationCenter defaultCenter] postNotificationName:name object:obj userInfo:nil];
    [obj release], obj = 0;

    [pool drain];
    return 0;
}
Centreboard answered 17/3, 2011 at 21:55 Comment(4)
Hi Justin ... are able to source the Apple Docs to support your answer. I've been on the hunt for a couple of hours, maybe I've missed it.Czarra
@Czarra i've expanded the answer. you can add a breakpoint at -MONObject release] if you also want to see the point execution where it's released. hope that serves as confirmation. if it were a void*, then definitely don't expect it to be retained, but object is an id.Centreboard
thank you very much. A very good demonstration. I wish I could award 2 'Right Answer' because your response helped compliment the other.Czarra
So my idea to remove the obj itself from the notifications in the dealloc is just... totally wrong.Illegitimate

© 2022 - 2024 — McMap. All rights reserved.