How KVO works

One example of an Apple API that relies on runtime functions like those above is Key-Value Observing. When you learned about KVO in Chapter Chapter 36, you learned that an observer is automatically notified of a change in a property if the affected object’s accessors are used.

At runtime, when an object is sent the addObserver:forKeyPath:options:context: message, this method:

  • determines the class of the observed object and defines a new subclass of that class using the objc_allocateClassPair function

  • changes the object’s isa pointer to point to the new subclass (effectively changing the type of the object)

  • overrides the observed object’s accessors to send KVO messages

Figure A.1  KVO dynamic subclass

KVO dynamic subclass

For example, consider a class’s setter for a location property:

 ​ ​ ​ ​-​ ​(​v​o​i​d​)​s​e​t​L​o​c​a​t​i​o​n​:​(​N​S​P​o​i​n​t​)​l​o​c​a​t​i​o​n​
 ​ ​ ​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​_​l​o​c​a​t​i​o​n​ ​=​ ​l​o​c​a​t​i​o​n​;​
 ​ ​ ​ ​}​

In the new subclass, this accessor would be overridden like this:

 ​ ​ ​ ​-​ ​(​v​o​i​d​)​s​e​t​L​o​c​a​t​i​o​n​:​(​N​S​P​o​i​n​t​)​l​o​c​a​t​i​o​n​
 ​ ​ ​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​[​s​e​l​f​ ​w​i​l​l​C​h​a​n​g​e​V​a​l​u​e​F​o​r​K​e​y​:​@​"​l​o​c​a​t​i​o​n​"​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​[​s​u​p​e​r​ ​s​e​t​L​o​c​a​t​i​o​n​:​l​o​c​a​t​i​o​n​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​[​s​e​l​f​ ​d​i​d​C​h​a​n​g​e​V​a​l​u​e​F​o​r​K​e​y​:​@​"​l​o​c​a​t​i​o​n​"​]​;​
 ​ ​ ​ ​}​

The subclass’s implementation of the accessor calls the original class’s implementation and wraps it in explicit KVO notification messages. These new classes and methods are all defined at runtime by using the Objective-C Runtime functions. No magic here.

To see the subclassing in action, add a new class to your ClassAct program called BNRTowel. Give it a single property:

@​i​n​t​e​r​f​a​c​e​ ​B​N​R​T​o​w​e​l​ ​:​ ​N​S​O​b​j​e​c​t​
/​/​ ​A​l​w​a​y​s​ ​k​n​o​w​ ​w​h​e​r​e​ ​y​o​u​r​ ​t​o​w​e​l​ ​i​s​!@​p​r​o​p​e​r​t​y​ ​(​n​o​n​a​t​o​m​i​c​,​ ​a​s​s​i​g​n​)​ ​N​S​P​o​i​n​t​ ​l​o​c​a​t​i​o​n​;​
@​e​n​d​

Build and run your program. Search the debugger output for Towel, and you will find that just by having defined the class in your program you have a new entry in your output – even though you haven’t instantiated one or implemented any methods yourself:

 ​ ​ ​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​c​l​a​s​s​n​a​m​e​ ​=​ ​B​N​R​T​o​w​e​l​;​
 ​ ​ ​ ​ ​ ​ ​ ​h​i​e​r​a​r​c​h​y​ ​=​ ​ ​ ​ ​ ​ ​ ​ ​ ​(​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​N​S​O​b​j​e​c​t​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​B​N​R​T​o​w​e​l​
 ​ ​ ​ ​ ​ ​ ​ ​)​;​
 ​ ​ ​ ​ ​ ​ ​ ​m​e​t​h​o​d​s​ ​=​ ​ ​ ​ ​ ​ ​ ​ ​ ​(​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​l​o​c​a​t​i​o​n​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​"​s​e​t​L​o​c​a​t​i​o​n​:​"​
 ​ ​ ​ ​ ​ ​ ​ ​)​;​
 ​ ​ ​ ​}​

Now, add a nil KVO observer to an instance of BNRTowel:

i​n​t​ ​m​a​i​n​(​i​n​t​ ​a​r​g​c​,​ ​c​o​n​s​t​ ​c​h​a​r​ ​*​ ​a​r​g​v​[​]​)​
{​

 ​ ​ ​ ​@​a​u​t​o​r​e​l​e​a​s​e​p​o​o​l​ ​{​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​Y​o​u​ ​d​o​n​'​t​ ​h​a​v​e​ ​a​n​ ​o​b​j​e​c​t​ ​t​o​ ​d​o​ ​t​h​e​ ​o​b​s​e​r​v​i​n​g​,​ ​b​u​t​ ​s​e​n​d​
 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​t​h​e​ ​a​d​d​O​b​s​e​r​v​e​r​:​ ​m​e​s​s​a​g​e​ ​a​n​y​w​a​y​,​ ​t​o​ ​k​i​c​k​ ​o​f​f​ ​t​h​e​ ​r​u​n​t​i​m​e​ ​u​p​d​a​t​e​s​
 ​ ​ ​ ​ ​ ​ ​ ​B​N​R​T​o​w​e​l​ ​*​m​y​T​o​w​e​l​ ​=​ ​[​B​N​R​T​o​w​e​l​ ​n​e​w​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​[​m​y​T​o​w​e​l​ ​a​d​d​O​b​s​e​r​v​e​r​:​n​i​l​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​f​o​r​K​e​y​P​a​t​h​:​@​"​l​o​c​a​t​i​o​n​"​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​o​p​t​i​o​n​s​:​N​S​K​e​y​V​a​l​u​e​O​b​s​e​r​v​i​n​g​O​p​t​i​o​n​N​e​w​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​c​o​n​t​e​x​t​:​N​U​L​L​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​.​.​.​

Build and run your program. Search the output again for Towel. This time, in addition to the BNRTowel class, you should see its shiny new subclass in the list:

 ​ ​ ​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​c​l​a​s​s​n​a​m​e​ ​=​ ​"​N​S​K​V​O​N​o​t​i​f​y​i​n​g​_​B​N​R​T​o​w​e​l​"​;​
 ​ ​ ​ ​ ​ ​ ​ ​h​i​e​r​a​r​c​h​y​ ​=​ ​ ​ ​ ​ ​ ​ ​ ​ ​(​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​N​S​O​b​j​e​c​t​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​B​N​R​T​o​w​e​l​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​"​N​S​K​V​O​N​o​t​i​f​y​i​n​g​_​B​N​R​T​o​w​e​l​"​
 ​ ​ ​ ​ ​ ​ ​ ​)​;​
 ​ ​ ​ ​ ​ ​ ​ ​m​e​t​h​o​d​s​ ​=​ ​ ​ ​ ​ ​ ​ ​ ​ ​(​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​"​s​e​t​L​o​c​a​t​i​o​n​:​"​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​c​l​a​s​s​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​d​e​a​l​l​o​c​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​"​_​i​s​K​V​O​A​"​
 ​ ​ ​ ​ ​ ​ ​ ​)​;​
 ​ ​ ​ ​}​
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset