惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
V2EX
J
Java Code Geeks
月光博客
月光博客
博客园_首页
The GitHub Blog
The GitHub Blog
Vercel News
Vercel News
B
Blog RSS Feed
博客园 - 聂微东
宝玉的分享
宝玉的分享
T
Tailwind CSS Blog
Jina AI
Jina AI
S
SegmentFault 最新的问题
B
Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
有赞技术团队
有赞技术团队
Hugging Face - Blog
Hugging Face - Blog
Google DeepMind News
Google DeepMind News
阮一峰的网络日志
阮一峰的网络日志
The Cloudflare Blog
量子位
Martin Fowler
Martin Fowler
博客园 - Franky
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗

Peter Steinberger

OpenClaw, OpenAI and the future | Peter Steinberger Shipping at Inference-Speed | Peter Steinberger The Signature Flicker | Peter Steinberger Just Talk To It - the no-bs Way of Agentic Engineering | Peter Steinberger Claude Code Anonymous | Peter Steinberger Live Coding Session: Building Arena | Peter Steinberger My Current AI Dev Workflow | Peter Steinberger Essential Reading for Agentic Engineers - August 2025 | Peter Steinberger Just One More Prompt | Peter Steinberger Poltergeist: The Ghost That Keeps Your Builds Fresh | Peter Steinberger Don't read this Startup Slop | Peter Steinberger Essential Reading for Agentic Engineers - July 2025 | Peter Steinberger Self-Hosting AI Models After Claude's Usage Limits | Peter Steinberger Logging Privacy Shenanigans | Peter Steinberger VibeTunnel's first AI-anniversary | Peter Steinberger Making AppleScript Work in macOS CLI Tools: The Undocumented Parts | Peter Steinberger Peekaboo 2.0 – Free the CLI from its MCP shackles | Peter Steinberger Command your Claude Code Army, Reloaded | Peter Steinberger Essential Reading for Agentic Engineers | Peter Steinberger Slot Machines for Programmers: How Peter Builds Apps 20x Faster with AI | Peter Steinberger My AI Workflow for Understanding Any Codebase | Peter Steinberger stats.store: Privacy-First Sparkle Analytics | Peter Steinberger Showing Settings from macOS Menu Bar Items: A 5-Hour Journey | Peter Steinberger VibeTunnel: Turn Any Browser into Your Mac's Terminal | Peter Steinberger Vibe Meter 2.0: Calculating Claude Code Usage with Token Counting | Peter Steinberger llm.codes: Make Apple Docs AI-Readable | Peter Steinberger Automatic Observation Tracking in UIKit and AppKit: The Feature Apple Forgot to Mention | Peter Steinberger Peekaboo MCP – lightning-fast macOS screenshots for AI agents | Peter Steinberger Migrating 700+ Tests to Swift Testing: A Real-World Experience | Peter Steinberger Commanding Your Claude Code Army | Peter Steinberger
Don't Call willChangeValueForKey Unless It's Really Neede...
Peter Steinberger · 2012-04-05 · via Peter Steinberger

You’re using KVO, right? So you most likely have already written code like this:

{% gist 2314685 %}

Carefully encapsulate your calls within a call to willChangeValueForKey/didChangeValueForKey to “enable” KVO. Well, turns out, you just did shit work. There’s no reason to do the will/did dance, as long as you are using a setter method to change the ivar. It doesn’t need to be backed by an ivar or declared as a property. KVO was written long before there was anything like @property in Objective-C.

In fact, I have been writing iOS apps for about four years and didn’t know this. A lot of open-source code also gets this wrong. Apple has some good KVO documentation, where it explains the concept of automatic change notifications.

There is a reason why you want to manually add willChangeValueForKey: most likely changing a variable also affects other variables. The most popular example is NSOperation:

{% gist 2314833 %}

First, it wonders why the heck NSOperation calls these methods, and second, it calls will/did on isExecuting, isFinished, and isReady. Not on isConcurrent.

So let’s try to figure out why. isConcurrent is defined like this:

{% gist 2324812 %}

It’s a simple accessor, thus can’t be overridden, and Apple has no reason to know when this changes; it’s returning a constant value, after all. But why the will/did on the other accessor methods?

Have a look at the implementation of the isReady method:

{% gist 2324831 %}

Notice how this is also only a getter, but rather than returning an ivar, it checks all kinds of things. This is why, when any of the things being checked is changed, KVO must be manually called.

So these will/did calls in each of the setters lets NSOperationQueue and other observers know that isReady has been updated, and they need to re-evaluate isReady’s value. This is a nice approach to prevent implementing setters for every value that isReady checks.

What Apple is doing here is combining keys for KVO on a higher level to reduce API clutter in the exposed class. Now we understand why it’s so complicated. However, for the average “MyClass”, this is usually overkill. Simple POCO objects (excuse me, switching from .NET-land ;) don’t need this.

If you own the whole accessor and thus control the setter as well, just implement that one and let KVO do the magic.

{% gist 2324840 %}

There’s also a second valid reason for using will/did, as Matt Gallagher explains here:

When you subclass an existing Cocoa class, its accessor methods may not automatically invoke KVO notifications even if they are not declared @dynamic. This is because existing accessor methods may directly access instance variables. (…) the solution is to add an appropriate set of -willChangeValueForKey: and -didChangeValueForKey: around the accessor method invocation.

There was a similar discussion on Cocoabuilder. Have fun learning!

For the StackOverflow junkies: Here’s a similar discussion from SO. My favorite is Josh Caswell’s answer, which neatly answers the original question: What is the purpose of will/didChangeValueForKey: When do I call these directly?

When you need to provide a KVO implementation in the absence of a property or accessor; when a change in one property affects another; when a single change affects many keys; when a change to a collection object happens without using the KVO methods.

Just a tidbit from the memory management side: Manual KVO will retain both old and new values (if you supply them), if the affected type is an object.

Update: There’s also Automatic Key-Value Observing for (Cocoa), a drop-in for manual KVO, but I haven’t tried it.

Update 2013: New tools make working with KVO much easier. Personal favorites: ReactiveCocoa and THObserversAndBinders.

Update 2014: Also check out KVOController, a simpler wrapper from Facebook.