TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Key-Value Observing Considered Harmful

9 pointsby stevenpover 11 years ago

4 comments

skueover 11 years ago
<i>&gt; KVO all comes through one method</i><p>Yes, and it&#x27;s annoying to have a long list of if statements. However, there&#x27;s a blocks based alternative since iOS4&#x2F;10.6, and a number of third-party variations.[1]<p><i>&gt; KVO is string-ly typed</i><p>That&#x27;s a big reason why libextobjc&#x27;s @keypath() macro is so popular.[2]<p><i>&gt; KVO requires you to handle superclasses yourself</i><p>That&#x27;s a feature, not a bug. If you use observeValueForKeyPath:ofObject:change:context: then you need to call super <i>just like overriding any other method.</i> This also gives you the flexibility to selectively decide to override behavior of your own superclasses.<p><i>&gt; KVO can crash when deregistering</i><p>Only if you deregister twice. And yes, it really sucks that you can accidentally deregister the same key path that a superclass deregisters, resulting in a crash. Much has been written about this issue, and third party libraries address it.[3]<p><i>&gt; KVO is a pit of failure</i><p>That&#x27;s a strong and subjective statement. Yes KVO can be frustrating for new developers - no argument there. But it does have its place.<p><i>&gt; KVO is implicit</i><p>Woah, no one (including Apple) is suggesting that apps use KVO for all of their message passing and dependencies. It has its place, especially for monitoring changes to Apple&#x27;s APIs or when multiple observers need to monitor the same object (again, that&#x27;s a feature not a bug).<p><i>&gt; KVO can cause infinite loops</i><p>Your handler should always avoid triggering the same event that triggered it. That&#x27;s not unique to KVO.<p><i>&gt; KVO is the old way</i><p>I remember when Apple introduced it, so I guess that makes me even older! Actually, Apple&#x27;s KVO is responsible for some of the newest JS libraries. SproutCore borrowed many of KVO&#x27;s ideas,[4] and you may be familiar with one of SproutCore&#x27;s notable forks: Ember.js<p><i>&gt; When is it okay to use KVO?</i><p>Agreed that these are great use cases for KVO. But doesn&#x27;t this counter the title of the post? It&#x27;s certainly not &quot;harmful&quot; to use KVO for these.<p>[1] <a href="https://github.com/search?l=Objective-C&amp;q=kvo&amp;source=cc&amp;type=Repositories&amp;s=stars" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;search?l=Objective-C&amp;q=kvo&amp;source=cc&amp;type...</a><p>[2] <a href="https://github.com/jspahrsummers/libextobjc/blob/master/extobjc/EXTKeyPathCoding.h" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;jspahrsummers&#x2F;libextobjc&#x2F;blob&#x2F;master&#x2F;exto...</a><p>[3] <a href="http://www.mikeash.com/pyblog/friday-qa-2012-03-02-key-value-observing-done-right-take-2.html" rel="nofollow">http:&#x2F;&#x2F;www.mikeash.com&#x2F;pyblog&#x2F;friday-qa-2012-03-02-key-value...</a><p>[4] <a href="http://guides.sproutcore.com/core_concepts_kvo.html" rel="nofollow">http:&#x2F;&#x2F;guides.sproutcore.com&#x2F;core_concepts_kvo.html</a>
icodestuffover 11 years ago
I disagree with a few points in this article, and can provide clarification on a few others. The clarifications first:<p>Bindings don&#x27;t exist in Cocoa Touch because they&#x27;re either slow (e.g. computed properties like @sum) because they&#x27;re mostly stateless, or memory intensive because... well, dig into the internals of KVO sometime - there are a huge number of caches to try to keep things fast. It&#x27;s not because KVO is a bad API. Heck, the KVO side of bindings is never exposed at all.<p>On the topic of infinite loops, yes, you have to be careful not to change an affecting property within an -observeValue... but it&#x27;s hardly unknowable what changes will cause a KVO notification. Indeed, it&#x27;s an isomorphic problem to breaking retain cycles, something every Obj-C programmer has to worry about every day, yes, even with ARC. The information is just stored in a different place, namely +keyPathsForValuesAffecting&lt;Key&gt; methods, rather than in property or ivar declarations. One can create a &quot;weak&quot; notification by removing oneself as an observer in the -observeValue, optionally adding oneself back at the end.<p>As for disagreements: KVO is not the old way. NSNotificationCenter and the delegate pattern predate KVO. Callback blocks don&#x27;t, and indeed where possible I&#x27;d recommend all of the above over KVO, but it&#x27;s hardly ancient, and certainly not &quot;the old way&quot;. It&#x27;s just a different way that allows you to watch for changes that doesn&#x27;t require the designers of an API to have provided hooks for you to do so explicitly.<p>On its implicitness, I can&#x27;t agree that it&#x27;s any more implicit than delegates. The same criticism that you can&#x27;t command-click in Xcode to follow the code flow applies. Same thing with NSNotifications for that matter. That&#x27;s kind of the point. If it was all explicit, we wouldn&#x27;t have the dynamism that all of these mechanisms provide.<p>Re: &quot;An important thing to note is that KVO will throw an exception and crash our app if we try to remove the same observer twice.&quot; This is simply untrue. KVO will throw an exception and crash the app if you try to remove the same <i>observance</i> twice, but an observance is created each time you call -addObserver:.... That is, like retain and release, -addObserver: and -removeObserver: calls need to be balanced. Additionally, the author actually misses a part where KVO really is broken: &quot;[Using a static context pointer per observation] helps to make sure that none of our super- or subclasses can deregister us from being an observer.&quot; doesn&#x27;t actually work. Using -removeObserver:forKeyPath: will happily remove the first observance it comes across (the first that was registered, AFAICT, though this isn&#x27;t documented), regardless of its context; it&#x27;s not just a convenience method for -removeObserver:forKeyPath:context: that passes NULL for the last parameter.<p>Lastly, it seems quite silly to have a unique context for each object and key path per class. If they&#x27;re going to unique the contexts, you don&#x27;t need to check objects and key paths. Or, you only need one context per class, and then only if your inheritance tree does include multiple observing classes. On a related note, I think the complaint about having to call super if the superclass implements -observeValue... is ridiculous. This is how any method that might be implemented at multiple levels of an inheritance tree must be called. Same thing with a delegate whose superclass also conforms to that delegate protocol. Or -init. Or -dealloc. Or...<p>.<p>All that said, I still generally agree with the conclusions about when to use KVO, although is #3 is just a subset of #1, and I wouldn&#x27;t have phrased it as the author did (see the first paragraph of disagreement). I&#x27;d also add #4: Use KVO when you need the old values as well as the new values of the objects, and&#x2F;or need to be notified prior to the value changing. NSNotificationCenter and delegates can do the same thing, but at the cost of double the number of methods that need to be written, and you&#x27;ll have to store the state yourself if you need the old value at the same time as the new value. That&#x27;s a lot of code that gets abstracted away by KVO, particularly if you&#x27;re observing multiple key paths on the same object and need all their old and new values. Code you don&#x27;t have to write is code you don&#x27;t have to debug.
jherikoover 11 years ago
&quot;When trying to be informed of changes on a class that you don’t own, such as one of Apple’s classes. A classic case of this is observing the contentSize of a table view. This information can’t be gotten in any other way.&quot;<p>I never like this - platform holders ramming their crap down your throat basically...<p>A broader version of this applies to Objective-C as a whole for me... I have to use it to interact with iOS or OS X in the intended way. There is no other reason for me to want to use it - the language features are not helpful for me, the ref counting is dangerous and the performance is horrendous (that last one is a design tradeoff to be fair - but I don&#x27;t want to pay for what I don&#x27;t use).
评论 #6844398 未加载
memracomover 11 years ago
Just use Reactive Cocoa.