1 #import <Foundation/Foundation.h>
3 // SourceBase will be the base class of Source. We'll pass a Source object into a
4 // function as a SourceBase, and then see if the dynamic typing can get us through the KVO
5 // goo and all the way back to Source.
7 @interface SourceBase: NSObject
11 - (SourceBase *) init;
12 - (uint32_t) getValue;
15 @implementation SourceBase
28 // Source is a class that will be observed by the Observer class below.
29 // When Observer sets itself up to observe this property (in initWithASource)
30 // the KVO system will overwrite the "isa" pointer of the object with the "kvo'ed"
33 @interface Source : SourceBase
38 - (void) setProperty: (int) newValue;
41 @implementation Source
48 - (void) setProperty: (int) newValue
50 _property = newValue; // This is the line in setProperty, make sure we step to here.
54 @interface SourceDerived : Source
58 - (SourceDerived *) init;
59 - (uint32_t) getValue;
62 @implementation SourceDerived
63 - (SourceDerived *) init
75 // Observer is the object that will watch Source and cause KVO to swizzle it...
77 @interface Observer : NSObject
81 + (Observer *) observerWithSource: (Source *) source;
82 - (Observer *) initWithASource: (Source *) source;
83 - (void) observeValueForKeyPath: (NSString *) path
85 change: (NSDictionary *) change
86 context: (void *) context;
89 @implementation Observer
91 + (Observer *) observerWithSource: (Source *) inSource;
95 retval = [[Observer alloc] initWithASource: inSource];
99 - (Observer *) initWithASource: (Source *) source
103 [_source addObserver: self
104 forKeyPath: @"property"
105 options: (NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
110 - (void) observeValueForKeyPath: (NSString *) path
111 ofObject: (id) object
112 change: (NSDictionary *) change
113 context: (void *) context
115 printf ("Observer function called.\n");
121 handle_SourceBase (SourceBase *object)
123 return [object getValue]; // Break here to check dynamic values.
129 Observer *myObserver;
131 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
133 mySource = [[SourceDerived alloc] init];
134 myObserver = [Observer observerWithSource: mySource];
136 [mySource setProperty: 5]; // Break here to see if we can step into real method.
138 uint32_t return_value = handle_SourceBase (mySource);
140 SourceDerived *unwatchedSource = [[SourceDerived alloc] init];
142 return_value = handle_SourceBase (unwatchedSource);