假设我有一个模型对象列表和一个控制器对象,它对单个模型对象的属性更改感兴趣。当我添加对象时,我使用addObserver为它感兴趣的每个键使用控制器和模型对象之间的KVO。现在,当其中一个观察到的对象消失时,我需要告诉视图控制器停止观察特定键对该单个对象的更改。
这样做的优雅方式是什么?我能想到的最好的方法是添加一个新的密钥kRemoveObject,我在我的控制器中调用addObserver,它在对象被删除之前被触发。然后我删除所有观察到的键,包括特定实例的kRemoveObject。有谁知道更干净的方式?这看起来有点麻烦。
答案 0 :(得分:0)
脱离我的头顶:
启用被观察对象以获取对控制器的引用。让被观察对象调用removeObserver:forKeyPath:functions。控制器必须提供keyPaths列表。
(编辑:执行此操作的一种超级干净的方法是为被观察对象定义委托协议(使用“imDying”方法),向被观察对象添加委托属性,将控制器设置为委托,并且让被观察对象在dealloc中调用委托的“imDying”方法。用更好的名称替换“imDying”,呵呵。)
或者:
让控制器管理被观察对象的生命周期,允许您在被观察对象deallocs之前移除自己。
答案 1 :(得分:0)
对于KVO,观察者应该保持对观察内容的参考。如果它这样做,那么对象永远不会“消失”(如果你的意思是被释放),因为观察者也有参考它。
如果您想停止观察它,请从观察者处进行观察。
如果您只是等待一个值更改,那么当您收到通知时 - 删除观察者。 (如果观察者已被移除,请采取预防措施不要移除观察者。)
在您的观察者的dealloc中,您将清理 - 删除对象上剩余的所有观察结果。
可能是在观察者中保持观察对象的数组以跟踪它们的情况 - 我已经看到过这种情况,但我不喜欢它并且它不是很灵活。
我喜欢的是一个叫做KVOHelper的课程。您可以在观察类中创建它,并将它传递给您正在观察的对象,观察者和关键路径。这是KVO的包装。如果你愿意,你可以删除观察者 - 或者只是释放KVOHelper并在它的dealloc例程中它会在释放所有内容之前移除观察者。它确保您不能多次删除同一个观察者(这会引发异常)。它还捆绑了一个KVOHelperSet,用于管理多个KVOHelper。我不能因为写这门课而受到赞誉 - 我是从一个我在一个项目上工作过的人那里得到的。但我现在一直使用它 - 它运作良好。原则很简单,您应该能够创建自己的原则。
答案 2 :(得分:0)
我发现这种非常优雅的方式,它解决了一直困扰我的关于KVO的事情,这是KVO用observeValueForKeyPath添加的大型“switch语句”。 KVO + Blocks非常酷,它消除了“switch语句”并且它自动处理了观察者的删除,因此在使用ARC时不需要调用removeObserver(如果你正在进行自己的内存管理,那么我认为你需要调用removeObserverWithBlockToken,尽管我没有尝试过)。
http://blog.andymatuschak.org/post/156229939/kvo-blocks-block-callbacks-for-cocoa-observers
此处的代码: https://gist.github.com/153676
有一点需要注意,但一般情况下块是正确的,如果你在你的块中引用self。你需要这样做:
__block blockSelf = self;
如果不这样做,您将最终获得保留周期。 (有关详细信息,请参阅Retain cycle on `self` with blocks)。
另一件事,如果你在文件上放置-fno-objc-arc,它可以与ARC一起使用。 (有关详细信息,请参阅此How can I disable ARC for a single file in a project?)
我希望Apple在SDK中添加类似的功能。