What is the KVO

KVO is key-value Observing. It is a derivative of the observer model. The basic idea is to add observation to an attribute of the target object. When the attribute changes, the KVO interface method implemented by the observer object is triggered to automatically notify the observer.

KVO implementation principle

The following code adds a KVO observation to the name attribute of the P object. Then make a breakpoint before adding observations.

LLDB debugging shows that the p object Class type was LGPerson before the addObserver method was executed.

Well, after executing the addObserve line, the Class type of the P object becomes

NSKVONotifying_LGPerson.

So what does NSKVONotifying_LGPerson have to do with LGPerson?

Or does this NSKVONotifying_LGPerson actually exist or is it dynamically generated?

It doesn’t matter. Let’s test it out.

Then another 27 lines of code to debug the breakpoint.

This shows that the NSKVONotifying_LGPerson does not originally exist, but is dynamically generated by the addObserve line.

NSKVONotifying_LGPerson is a subclass of LGPerson.

Place two breakpoints on the remove observer code.

By printing information we can see that self.p isa pointer is pointing to when addObserve

NSKVONotifying_LGPerson, after removeObserver, the isa pointer to self.p is pointed back

LGPerson.

The NSKVONotifying_LGPerson class automatically generates several methods, as shown in the figure below.

The key is this setName method. It is this setName that implements the function.

So what does this setName method do?

So let’s do two break points first. On line 26, type watchpoint set variable self->_p->_name.

Watchpoint set variable Watches whether a value is changed

Then you break 26 lines of code. When we assign self.p.name at line 28, the code breaks.

As you can see, before assigning self.p.name, before calling p’s setName method, the system also calls these two methods.

This method has NSKeyValueWillChange and nskey value edichange.

This is why observing changes in member variables does not work. Because setter methods are not generated

So why is it that a member variable can be observed with setValue:forKey, which generates the corresponding callback?

This requires the use of GNUstep source code, although GNUstep is not apple’s official source code, but there is a high reference value

Search observeValueForKeyPath in GNUstep

Indicates that the observed object received a -setValue:forKey: message, or that a key-value encoding compatible set method key has been called,

Or – willChangeValueForKey:

Or -didChangevalueForKey: to have been called.

One caveat: willChangeValueForKey and didChangeValueForKey must be paired.

So when is observeValueForKeyPath called?

Is through notifyForKey.

The notifyForKey method is invoked in the didChangeValueForKey method

ObserveValueForKeyPath callback.

conclusion

Therefore, the implementation principle of KVO is as follows: when we call addObserve, it will dynamically generate a subclass of the current class starting with NSKVONotifying_. The isa pointer of the object will point to this class, and the system will automatically generate the corresponding method.

This system-generated subclass goes back and calls the corresponding setter method, and inside this setter method, it’s actually calling

WillChangeValueForKey and didChangeValueForKey.

The notifyForKey method is then invoked inside the didChangeValueForKey method

ObserveValueForKeyPath callback.

More dry goods in the “Logical iOS technology number”