NSNotification概念 - 代码片段在哪里?

时间:2011-01-22 16:12:33

标签: objective-c cocoa notifications event-bubbling

我的一部分认为我理解NSNotification概念。它是一个基于字符串的通知的集中式广播系统。张贴在一侧,在一侧或多侧观察并采取相应行动。然而,我的另一部分,必须编写代码的部分,每次我需要通知时都会感到困惑。什么样的代码进入哪个头/实现,什么文件实际上进行观察以及如何防止它变得混乱?是时候理顺了,你能帮我验证一下这些假设吗?我对第4名相当自信,但是第5名遇到了混乱的大奖。


  1. NSNotifications是在[NSNotification defaultCenter]的帮助下创建的,没有分配/初始化NSNotification。正确的吗?
  2. 执行postNofification专长的对象始终将self传递到发布代码:[[NSNotificationCenter defaultCenter] postNotificationName:@"note name" object:self]。正确的吗?
  3. 事件冒泡存在于其他语言中,但不存在于使用NSNotification的Objective-C中。您没有传递通知,您将通知名称设置为足以进行全局广播。正确的吗?
  4. 如果您仍想传递对象A发布的通知,则在B中观察它,处理它并发布一个新的,更具体的通知,以便观察对象C.例如。从A到B @"MenuItemTapped",从B到C @"NavigateTo"正确吗?
  5. 通知的名称是NSString。因为海报和观察者都希望避免拼写错误,我们将NSString常量存储在 [extern const | define | class method | none of the above] 中。你能帮我挑一个吗?
    • 尝试创建类似NotificationNames.h文件的内容,其中包含所有extern NSString *const NOTE_NAME声明。然而,这破坏了通知的可移植性。
    • 另一个尝试是子类化NSNotification(使用XCode模板来保持创建速度快),但是因为这个概念来自AS3中的子类化事件类,所以它似乎非常不客观 - c-ish。还有一种奇怪之处就是你无法在NSNotification上调用[super init],所以事情开始变得无法控制。
    • 我对这个问题的麻烦来自繁琐的#import陈述。如何最大限度地减少拼写错误,同时保持常量/定义可移植?

2 个答案:

答案 0 :(得分:4)

你大多都得到了它。您的数字1-3通常是正确的。

  • 您不应该需要分配自己的NSNotification对象。
  • 您通常会将“自我”作为通知的“对象”传递,但如果您在概念上通知“代表”其他内容,您也可以传递其他内容。但那种情况不太常见。
  • 通知与UI中的“事件”不同。可可确实有事件;它们是鼠标/键盘/触摸事件,它们通过UI对象“冒泡”“响应者链”。通知是一种完全独立的机制,与UI无关,它通常用于其他解耦/独立对象之间的全局广播。它更像是为一个对象提供多个委托。
  • 是的,您应该在每个使用它的人都可以看到的通知名称中定义。在Cocoa本身,这通常是一个带有extern NSString *const UIKeyboardDidShowNotification声明的公共标题。在一些私有实现文件中是定义。

关于您上面#4的特别说明。将通知视为通知,而不是指示。他们通常捕捉状态变化或广泛有趣的事件。 “MenuItemTapped”是一个合理的通知,但“NavigateTo”通常不是,因为暗示是你告诉某个特定对象在某处导航。如果是这种情况,那个对象应该是想要导航的东西的委托(或者应该是属性),你应该让它直接发生。当然,这不是必需的,您可以根据需要使用该机制。但是Cocoa的设计模式通常不会使用“告诉对象做什么”的通知,只是为了“告诉谁关心会发生什么/做什么”。有意义吗?

最后,特别是:#4中的例子 - 那些听起来像真正的UI事件,似乎整个事情可以通过委托来处理,除非有一些理由说明为什么这些对象需要如此分离。

答案 1 :(得分:2)

  1. 如果您愿意,可以直接创建NSNotification个对象。 postNotificationName:object:只是一种为您创建,配置和发布通知对象的便捷方法。

  2. 您可以传递任何您喜欢的对象。其目的是允许通知订阅者仅接收有关特定对象的通知,因此理想情况下,您传递通知所针对的对象,通常 - 但不总是 - self

  3. 通知不是事件。它们是应用程序中的全球广播。

  4. 您不会向特定对象发送通知 - 它们是广播。如果要向特定对象发送消息,只需在该对象上调用方法即可。

  5. 头文件中的Externs很好。