【问题标题】:Best approach for multiple notification: delegate vs KVO多重通知的最佳方法:delegate vs KVO
【发布时间】:2017-05-25 13:55:01
【问题描述】:

我有三个类共享NSObject 子类的同一个实例。

所有这三个类都可以修改该共享实例属性,并且当发生这种情况时,该共享实例必须通知所有其他三个类 X 变量已更改。

这是使用KVO的完美场景,但我认为这是非常不一致的代码,包含很多硬编码的字符串,因此不会发生编译时警告或检查,出现问题时很难获取堆栈跟踪,在重构代码的情况下,更改所有内容并祈祷不要忘记任何内容是一件令人头疼的事情,在解除分配时手动删除观察者,通过向所有类添加相同的观察者来重复大量代码等。

由于这个原因,我认为delegates 可能是解决大多数(如果不是全部)这些问题的好方法。易于实现,非常清晰和有文档记录,如果编译器告诉你有什么改变,不需要手动设置为 nil 任何东西,不需要硬编码的字符串,出现问题时明显的 stracktrace 等等。

我的delegate 方法将覆盖所有变量的setters,我想监听它们的变化并在那里调用委托,以便所有类都可以知道该变化。

您如何看待这种方法?

提前谢谢你!

【问题讨论】:

  • 共享实例子类将只有一个带有n 可选方法的协议。其余的类必须实现该协议才能监听共享实例的变化。
  • 您是否考虑过使用 NotificationCenter 处理多个通知?
  • NSNotificationCenterKVO 非常相似,但KVO 仅用于控制变量,而这正是我所需要的。所以NSNotificationCenter 的问题与使用KVO 时的问题完全相同:硬编码字符串、重构时头痛、未记录、重复代码等......

标签: ios objective-c delegates key-value-observing


【解决方案1】:

虽然您是完全正确的,但您将需要使用 KVO 的键路径的硬编码字符串,我可以说,在几个大型应用程序上工作这很少是问题。

委托解决方案可以工作,但是您需要跟踪委托(在您的情况下,听起来您需要跟踪一组委托)。无论如何,您使用它的方式类似于您在 KVO 中注册/注销的方式。

您描述的问题正是观察者模式应该解决的问题,而 Cocoa 为您提供了该模式的内置解决方案

我的建议(大部分你可能知道):
1) 用于 keyPath 的 extern 常量,所有 3 个类都可以使用
2)当您的观察者之一收到对象的引用时,将观察者注册到-addObserver:...
3) 确保您正确拨打-removeObserver:...
4) 在-observeValueForKeyPath:... 中,将 keypath 与您的 const 进行比较,并将您的处理放在那里

但正如您所提到的,可能出现的主要问题是 keyPath 是否发生变化。您的代码仍将编译,并且您不一定会在运行时立即发现问题。

如果这是一个真正的问题,您可以编写一个调用 -addObserver:... 的包装器方法,但首先检查接收者是否响应 keyPath 参数。

虽然我从来没有这样做过,而且正如我所提到的,我从来没有真正遇到过 KVO 的 keyPath 问题。通常,如果有人进入并重命名 keyPath,他们会进行工作区搜索并看到硬编码的字符串也需要更改

总之,我个人更喜欢 KVO 解决方案而不是委托通知解决方案,但最终你是对的,因为你可能会错过 KVO 的错误

【讨论】:

  • 非常感谢您的回答!在做了一些研究之后,我决定使用delegates,因为我认为一切最终都会更加紧密。正如您所说,它是一个代表数组,但我使用的是 NSHashTable 初始化为 weakObjectsHashTable,因此我不需要调用 KVO 的 -removeObserver:... 等效项。更多信息在这里:stackoverflow.com/a/23671452/7843625。在做了一些测试之后,我发现执行委托比使用KVO 发送通知要快。纳秒级的差异,但确实存在!哈哈
  • 酷!感谢您的回复,实际上我什至从未听说过NSHashTable。虽然我有点困惑,因为我一直认为 HashTable == Dictionary,AKA 有键/值对,但是基于链接的答案,看起来你可以像插入数组一样将对象插入其中?如果是这样,为什么不使用数组呢? NSArrays 是否创建对其包含的对象的强引用?
  • 正如你所说,NSArray 创建了它包含的对象的强引用。使用NSArray 不会有任何问题,但我必须注意在释放NSObject 之前删除该引用。我不是NSHashTable 的专家,因此请参阅 Apple 文档以获取更多信息:developer.apple.com/reference/foundation/nshashtable。是的,它的行为类似于NSArray。事实上,我认为它是NSSet的子类。
猜你喜欢
  • 1970-01-01
  • 2012-05-19
  • 1970-01-01
  • 2021-03-31
  • 1970-01-01
  • 2013-07-08
  • 2019-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多