39

我正在尝试使用 NSNotificationCenter 将 NSDictionary 从 UIView 传递给 UIViewController。发布通知时字典工作正常,但在接收方法中我无法访问字典中的任何对象。

这是我创建字典和发布通知的方式...

itemDetails = [[NSDictionary alloc] initWithObjectsAndKeys:@"Topic 1", @"HelpTopic", nil];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"HotSpotTouched" object:itemDetails];

在 UIViewController 我正在设置观察者......

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

出于测试目的,hotSpotMore 看起来像这样......

- (void)hotSpotMore:(NSDictionary *)itemDetails{
      NSLog(@"%@", itemDetails);
      NSLog(@"%@", [itemDetails objectForKey:@"HelpTopic"]);    
}

第一个 NSLog 可以很好地显示字典的内容。第二个日志引发以下异常...

 [NSConcreteNotification objectForKey:]: unrecognized selector sent to instance 0x712b130

我不明白为什么我无法访问传递的字典中的任何对象。

提前感谢您的帮助。

约翰

4

3 回答 3

111

第一个 NSLog 可以很好地显示字典的内容。第二个日志引发以下异常...

该程序试图欺骗您,它看起来就像是您的字典,因为您的字典在通知中。从异常中您可以看到您的对象实际上来自一个名为 NSConcreteNotification 的类。
这是因为通知方法的参数始终是 NSNotification 对象。这将起作用:

- (void)hotSpotMore:(NSNotification *)notification {
      NSLog(@"%@", notification.object);
      NSLog(@"%@", [notification.object objectForKey:@"HelpTopic"]);    
}

只是作为一个提示:对象通常是发送通知的对象,您应该将您的 NSDictionary 作为 userInfo 发送。
如果您这样做,我认为它会改进您的代码:

NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center postNotificationName:@"HotSpotTouched" object:self userInfo:itemDetails];


- (void)hotSpotMore:(NSNotification *)notification {
      NSLog(@"%@", notification.userInfo);
      NSLog(@"%@", [notification.userInfo objectForKey:@"HelpTopic"]);    
}

object 参数用于区分可以发送通知的不同对象。
假设您有两个不同的 HotSpot 对象,它们都可以发送通知。当您设置objectin时,addObserver:selector:name:object:您可以为每个对象添加不同的观察者。使用 nil 作为对象参数意味着应该接收所有通知,而不管发送通知的对象是什么。

例如:

FancyHotSpot *hotSpotA;
FancyHotSpot *hotSpotB;

// notifications from hotSpotA should call hotSpotATouched:
[[NSNotificationCenter defaultCenter] addObserver:self 
       selector:@selector(hotSpotATouched:) name:@"HotSpotTouched" 
       object:hotSpotA]; // only notifications from hotSpotA will be received

// notifications from hotSpotB should call hotSpotBTouched:
[[NSNotificationCenter defaultCenter] addObserver:self 
       selector:@selector(hotSpotBTouched:) name:@"HotSpotTouched" 
       object:hotSpotB]; // only notifications from hotSpotB will be received

// notifications from all objects should call anyHotSpotTouched:
[[NSNotificationCenter defaultCenter] addObserver:self 
       selector:@selector(anyHotSpotTouched:) name:@"HotSpotTouched" 
       object:nil]; // nil == “any object”, so all notifications with the name “HotSpotTouched” will be received


- (void)hotSpotATouched:(NSNotification *)n {
    // only gets notification of hot spot A
}

- (void)hotSpotBTouched:(NSNotification *)n {
    // only gets notification of hot spot B
}

- (void)anyHotSpotTouched:(NSNotification *)n {
    // catches all notifications
}
于 2010-11-08T20:01:26.933 回答
4

这是使用 NSNotification 传递字典数据的最佳方式。

发布通知:

 [[NSNotificationCenter defaultCenter] postNotificationName:@"Put Your Notification Name" object:self userInfo:"Pass your dictionary name"];

添加观察者处理通知。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mydictionaryData:)  name:@"Put Your Notification Name" object:nil];

放置通知处理程序方法。

- (void)mydictionaryData::(NSNotification*)notification{
   NSDictionary* userInfo = notification.userInfo;
   NSLog (@"Successfully received test notification! %@", userInfo);}

我希望,这个解决方案会帮助你

于 2013-03-18T08:20:32.743 回答
3

Matthias 正在谈论的方法,我认为您应该使用的方法是

postNotificationName:object:userInfo:

其中 object 是发件人,而 userInfo 是您的字典。

于 2012-02-02T20:46:51.980 回答