3

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


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

2 回答 2

4

你已经得到了它。您的数字 1-3 通常是正确的。

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

关于您上面的#4 的特别说明。将通知视为通知,而不是说明。它们通常捕获状态变化或广泛有趣的事件。“MenuItemTapped”是一个合理的通知,但“NavigateTo”通常不是,因为这意味着你正在告诉某个特定的对象导航到某个地方。如果是这种情况,该对象可能应该是需要导航的事物的委托(或应该是属性),并且您应该直接使其发生。当然,这不是必需的,您可以根据需要使用该机制。但是 Cocoa 设计模式通常不使用通知来“告诉对象该做什么”,而只使用“告诉谁关心将会/确实发生什么”。

最后,特别是:您在#4 中的示例——这些听起来像是真正的 UI 事件,并且似乎整个事情都可以通过委托来处理,除非出于某种原因需要将这些对象如此解耦。

于 2011-01-22T16:25:45.430 回答
2
  1. NSNotification如果您愿意,您可以直接创建对象。postNotificationName:object:只是一种为您创建、配置和发布通知对象的便捷方法。

  2. 你可以传递任何你喜欢的对象。其目的是允许通知订阅者仅接收有关特定对象的通知,因此理想情况下,您传入通知所涉及的对象,这通常(但并非总是)是self.

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

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

  5. 头文件中的外部很好。

于 2011-01-22T16:31:27.680 回答