为何苹果KVO实现采用子类化而非method_exchangeImplementations?
method_exchangeImplementations Great question—this cuts right to why Apple's KVO implementation is designed the way it is, and it all boils down to flexibility, scope control, and avoiding unintended side effects. Let's break it down:
1. KVO is per-object, not per-class
method_exchangeImplementations swaps method implementations at the class level, meaning every instance of that class (and any subclasses that inherit the method) would start behaving differently. But KVO's whole point is to track changes only for specific objects that have observers attached.
For example: If you have two Person instances, and only one is being observed for its name property. Using method swizzling would make both instances fire KVO notifications when setName: is called—even the one no one's watching. Subclassing fixes this by swapping the observed object's isa pointer to point to a KVO-generated subclass (like NSKVONotifying_Person). Only that single instance uses the subclass's modified setter; all others stay as regular Person instances.
2. Cleanly encapsulates KVO logic without polluting the original class
When KVO creates a subclass, it can safely override the setter method to inject the required KVO boilerplate:
- (void)setName:(NSString *)name { [self willChangeValueForKey:@"name"]; [super setName:name]; // Calls the original class's setter [self didChangeValueForKey:@"name"]; }
This keeps all the KVO-specific code contained in the auto-generated subclass. The original class's implementation stays untouched—no need to save references to the original method, no risk of conflicting with other swizzling that might happen on the same method.
If we used method_exchangeImplementations, we'd have to:
- Save the original setter implementation
- Write a custom method that handles the KVO notifications and calls the original
- Swap them, and then worry about un-swapping later if observers are removed. This gets messy fast, especially with multiple observers or dynamic observation changes.
3. Handles dynamic observer addition/removal gracefully
KVO lets you add and remove observers at runtime. With subclassing, when the last observer is removed from an object, Apple can simply swap its isa pointer back to the original class—no lingering swizzled methods affecting future behavior.
Method swizzling doesn't offer this kind of granularity. Un-swizzling a method would affect all instances, not just the one that no longer has observers. That's a non-starter for a system designed to be dynamic and non-intrusive.
4. Preserves the illusion of the original class
The auto-generated KVO subclass overrides the class method to return the original class's name. So when you call [observedObject class], you get Person instead of NSKVONotifying_Person. This keeps the implementation details hidden from developers, so your code doesn't have to handle weird edge cases where an object's class suddenly looks different.
Method swizzling can't fake this kind of transparency—swizzling a method doesn't change the object's class identity, but it does alter behavior globally, which is easier to accidentally detect (and break) in code.
内容的提问来源于stack exchange,提问作者Sterling William

