Struggling to get the Dictionary passed with NSNotification - iphone

I received the notification so I handle it like so
-(void) dateSelected:(NSNotification *) notification
{
NSLog(#"Value: %#", [[notification userInfo] valueForKey:#"date"] );
NSMutableDictionary * dateDict = [[NSDictionary alloc] initWithDictionary:[notification userInfo]];
NSLog(#"The Date Dict: %#", dateDict );
}
The logs I get are
2012-07-20 11:32: TestApp[10701:40b] Value: (null)
2012-07-20 11:32: TestApp[10428:40b] The Date Dict: {
}
If I NSLog out the notification itself it looks valid:
2012-07-20 11:33: TestApp[10457:40b] Notification: NSConcreteNotification 0x16629460 {name = date_selected_; object = {
date = 20120705;
}}
I've done this before and its worked.
I'm sure its simple, but today I cannot see the issue.
Any help would be appreciated.
Thanks,
-Code

It's pretty simple, look at your log output ... There's no userInfo set in your notification. There's just name and object. Compare your output with this one ...
NSNotification *notification = [NSNotification notificationWithName:#"NAME"
object:self
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:#"obj", #"key", nil]];
NSLog( #"NOT: %#", notification );
...
NOT: NSConcreteNotification 0x73586f0 {name = NAME;
object = <CMAppDelegate: 0x884a4e0>; userInfo = {
key = obj;
}}
... see the difference? There's name, object, but also userInfo in log output.
So the answer is - your notification does not contain userInfo dictionary. Look at code which fires this notification.

Related

Pass object with NSNotificationCenter to other view

I am trying to pass an object from my main view class to other notification receiver in another class.
I want to pass an object named country, that loads all the cities from an SOAP Request in the Main Controller and i want to send it to my next view.
country = [[Country alloc] init];
Country header:
#interface Country : NSObject
{
NSString *name;
NSMutableArray *cities;
}
#property (nonatomic,retain) NSString *name;
- (void)addCity:(Cities *)city;
- (NSArray *)getCities;
- (int)citiesCount;
#end
I found a way to pass data with NSNotificatios is using a NSDictionary in UserInfo. But its not possible to send the whole object instead of converting to an NSDictionary? Or what's the best way to transfer it? Im stuck trying to figure out how to pass the objects.
Actually i got working this simple NSNotification on my App.
NSNotification in the Main View Controller implementation:
//---Call the next View---
DetailViewController *detail = [self.storyboardinstantiateViewControllerWithIdentifier:#"Detail"];
[self.navigationController pushViewController:detail animated:YES];
//--Transfer Data to2View
[[NSNotificationCenter defaultCenter] postNotificationName:#"citiesListComplete" object:nil];
NSNotification in 2View Controller implementation:
// Check if MSG is RECEIVE
- (void)checkMSG:(NSNotification *)note {
NSLog(#"Received Notification");
}
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(checkMSG:)
name:#"citiesListComplete" object:nil];
Oooooo, so close. I have a feeling you do not understand what an NSDictionary is though.
Post your notification with this:
Country *country = [[[Country alloc] init] autorelease];
//Populate the country object however you want
NSDictionary *dictionary = [NSDictionary dictionaryWithObject:country forKey:#"Country"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"citiesListComplete" object:nil userInfo:dictionary];
then get the country object like this:
- (void)checkMSG:(NSNotification *)note {
Country *country = [[note userInfo] valueForKey:#"Country"];
NSLog(#"Received Notification - Country = %#", country);
}
You don't need to convert your object into a NSDictionary. Instead, you need to send a NSDictionary with your object. This allows you to send lots of information, all based on keys in the NSDictionary, with your NSNotification.
For Swift
You can pass dictionary with using the below code
NSNotificationCenter.defaultCenter().postNotificationName(aName: String, object anObject: AnyObject?, userInfo aUserInfo: [NSObject : AnyObject]?)
for example
NSNotificationCenter.defaultCenter().postNotificationName("OrderCancelled", object: nil, userInfo: ["success":true])
And read this dictionary from
func updated(notification: NSNotification){
notification.userInfo?["success"] as! Bool
}

facebook connect not working

This all is driving me nuts.
I just integrated facebook in my iphone app.
After typing in my username and password in the login dialog this method is called.
- (void)request:(FBRequest*)request didLoad:(id)result {
if ([request.method isEqualToString:#"facebook.fql.query"]) {
NSLog(#"result %#",result);
NSArray* users = result;
NSLog(#"users %#",users);
NSDictionary* user = [users objectAtIndex:0];
NSString* name = [user objectForKey:#"name"];
self.facebookName = name;
if (_posting) {
[self postToWall];
_posting = NO;
}
}
}
But after this the app crashes most of the times and when I tried to log the "result" array it appears to be empty. Why is it so?
What should I do? Please suggest.
use this code
NSArray *users=[[NSArray alloc]initWithObjects:result, nil];
NSLog(#"users %#",users);
NSDictionary* user = [[NSDictionary alloc]initWithObjectsAndKeys:users,#"users", nil];
NSLog(#"%#",user);
I got the reason for this.
This was due to the session getting lost frequently in between.
So I had to call [session resume] in the facebook login action event
and in this manner if at all the session is lost by any chance then the previous session is resumed and the "result" does not appears to be nil in (void)request:(FBRequest*)request didLoad:(id)result method.
Hope this helps out those who are stuck in the same issue.

iPhone Development: nil userInfo when receiving a notification

I post the notifications like this in an operation:
DownloadStatus * status = [[DownloadStatus alloc] init];
[status setMessage: #"Download started"];
[status setStarted];
[status setCompleteSize: [filesize intValue]];
[userInfo setValue:status forKey:#"state"];
[[NSNotificationCenter defaultCenter]
postNotificationName:[targetURL absoluteString]
object:nil userInfo:userInfo];
[status release];
DownloadStatus is an object that contains some information abou the download that is being currently downloaded. userInfo is a property of the object that has been initialized in the init part and is kept for the complete duration of the operation. It is created so:
NSDictionary * userInfo = [NSDictionary dictionaryWithObject:targetURL
forKey:#"state"];
"targetURL" is a NSString, I use this just to make sure everything is working fine. When I receive the event - I registered like this:
[[NSNotificationCenter defaultCenter]
addObserver:self selector:#selector(downloadStatusUpdate:)
name:videoUrl
object:nil];
Here "videoUrl" is a string that contains the url being downloaded, so that I will receive notification about an url I'm waiting to see downloaded.
The selector is implemented like this:
- (void) downloadStatusUpdate:(NSNotification*) note {
NSDictionary * ui = note.userInfo; // Tried also [note userInfo]
if ( ui == nil ) {
DLog(#"Received an update message without userInfo!");
return;
}
DownloadStatus * state = [[ui allValues] objectAtIndex:0];
if ( state == nil ) {
DLog(#"Received notification without state!");
return;
}
DLog(#"Status message: %#", state.message);
[state release], state = nil;
[ui release], ui = nil; }
But this selector always receives a null userInfo. What am I doing wrong?
MrWHO
One way or another, you seem to be initialising your userInfo object incorrectly. The line as given:
NSDictionary * userInfo = [NSDictionary dictionaryWithObject:targetURL
forKey:#"state"];
Would create an autoreleased NSDictionary and store it to a local variable. The value would not be propagated up to your member variable.
Supposing that's a snippet, followed by e.g.
self.userInfo = userInfo;
to assign the local to the member, retaining it at the same time, then your code should generate an exception at this line:
[userInfo setValue:status forKey:#"state"];
Since it attempts to mutate an immutable object. It's therefore much more likely that the value of userInfo isn't stored and you're messaging nil at that point.
So, I would think that — assuming you have userInfo declared as a 'retain' type property, you want to replace:
NSDictionary * userInfo = [NSDictionary dictionaryWithObject:targetURL
forKey:#"state"];
With:
self.userInfo = [NSMutableDictionary dictionaryWithObject:targetURL
forKey:#"state"];

Objective C - How to access NSNotification inner objects?

I want to access a inner object from a notification. I need to get the key AVSystemController_AudioVolumeChangeReasonNotificationParameter.
If I call [sender object] I get this output. But if I call
[[sender object] userInfo]
I only get "unrecognized selector sent to instance". Why is that?
NSLog(#"%#", [sender object]) output:
NSConcreteNotification 0x157a30 {name = AVSystemController_SystemVolumeDidChangeNotification; object = AVSystemController: 0x1616c0; userInfo = {
"AVSystemController_AudioCategoryNotificationParameter" = "Audio/Video";
"AVSystemController_AudioVolumeChangeReasonNotificationParameter" = ExplicitVolumeChange;
"AVSystemController_AudioVolumeNotificationParameter" = 1;
}}
If it is not possible to access userInfo, can I get the output of NSLog to do a string search?
Your output from NSLog actually looks like the output of
NSLog(#"%#", sender);
Are you sure you were calling [sender object]?
object is often the Object that posted the notification. In your case most likely an object with class AVSystemController
The userinfo can be accessed with
[sender userInfo]
So please try
NSLog(#"%#", [sender userInfo]);
BTW: If you try to map the function of the volume-buttons to some other function (for example "Take Photo"-Action) your app won't be approved. Just in case.

Cocoa: Problem passing a CGPoint with NSNotification and NSDictionary

I'm trying to fire a Notification in a method called setPosition in one class, that triggers setViewPointCenter in another class. However, I'm trying to send a CGPoint along with it. But Xcode isn't liking it one bit.
-(void)setPosition:(CGPoint)point
{
NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:#"sp", point, nil];
[[NSNotificationCenter defaultCenter]
postNotificationName:#"SpriteDidSetPosition"
object:self
userInfo:dict];
[super setPosition:point];
}
Triggers this method in another class, but throws the indicated error
-(id) init{
// Usual stuff, blah blah blah...
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(setViewPointCenter:)
name:#"BownceSpriteDidSetPosition"
object:nil];
}
-(void) setViewPointCenter:(NSNotification *)notification
{
// ERROR: Invalid Initializer
CGPoint point = [[notification userInfo] valueForKey:#"sp"];
// more code here....
}
I've been digging around, and found this solution, but I still get an error.
-(void)setPosition:(CGPoint)point
{
// ERROR: Incompatile type for argument 1 of "Value With Point"
NSValue *pointAsObject = [NSValue valueWithPoint:point];
NSDictionary *dict = [[NSDictionary alloc]
initWithObjectsAndKeys:#"sp",
pointAsObject,
nil];
[[NSNotificationCenter defaultCenter]
postNotificationName:#"SpriteDidSetPosition"
object:self
userInfo:dict];
[super setPosition:point];
}
It's driving me nuts. And to confuse me even further, changing CGPoint to NSPoint like this
-(void)setPosition:(NSPoint)point
{
NSValue *pointAsObject = [NSValue valueWithPoint:point];
NSDictionary *dict = [[NSDictionary alloc] init];
[dict initWithObjectsAndKeys:#"sp", pointAsObject, nil];
[[NSNotificationCenter defaultCenter]
postNotificationName:#"SpriteDidSetPosition"
object:self
userInfo:dict];
[super setPosition:CGPointMake(point.x, point.y)];
}
Get's rid of the error in setPosition, but I'm still screwed in setViewPointCenter. And as I understand it, CGPoint and NSPoint should equal the same thing, but it doesn't look like they do.
Does anyone have a working example of how to pass a CGPoint in a Dictionary? I can't figure it out.
This is for the iPhone, incase that makes a difference.
Try using +[NSValue valueWithCGPoint].
I'd use the NSStringFromCGPoint() function to convert it to a string, and then use the CGPointFromString() function to convert it back.
You could encapsulate the x and y values from the CGPoint into NSNumber objects using +numberWithFloat: and then add the two resulting NSNumber objects into the dictionary. You can then reconstruct the CGPoint on the other side using:
CGPoint myPoint;
myPoint.x = [myNumberObject floatValue];
myPoint.y = [myNumberObject2 floatValue];
The reason it didn't work in the first try was that CGPoint isn't an object, it's a C struct.
Its been too long time after #Ben Gottlieb have given an answer, his answer is well, but for future I'm keeping an example for reference.
// In example, I want to send CGPoint with notification
[[NSNotificationCenter defaultCenter] postNotificationName:#"MyNotification" object:#{#"someKeyToHoldCGPoint":[NSValue valueWithCGPoint:CGPointMake(10, 10)]}];
- (void) getPoints:(NSNotification *)notification {
//get the dictionary object from notification
NSDictionary *p = (NSDictionary *)notification.object;
//get the NSValue object from dictionary p
NSValue *value = [p valueForKey:#"someKeyToHoldCGPoint"];
//convert the value to CGPoint
CGPoint points = [value CGPointValue];
//check if we've the correct value
NSLog(#"%#",NSStringFromCGPoint(points));
}
It should log, (10,10).
I haven't read up on GC and NSPoints, but what data-types can NSDictionary hold? Check the docs, maybe you should cast it to NSData.