多重通知的最佳方法:委托与KVO

时间:2017-05-25 13:55:01

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

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

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

这是使用KVO的完美场景,但我认为它是非常不一致的代码,有很多硬编码字符串,因此没有编译时警告或检查发生,当事情发生时很难获得堆栈跟踪错误,如果重构代码,改变一切并祈祷不要忘记任何东西,在解除分配时手动删除观察者,通过向所有类添加相同的观察者等重复大量代码,这是一件令人头痛的事。

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

我的delegate方法将覆盖我想要听取其更改的所有变量'setters,并在那里调用委托,以便所有类都能知道该更改。

您如何看待这种方法?

提前谢谢!

1 个答案:

答案 0 :(得分:0)

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

委托解决方案可以工作,但是你需要跟踪代表(在你的情况下,听起来你需要跟踪一组代表)。你使用它的方式与你注册/取消注册KVO的方式类似。

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

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

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

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

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

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