1*99451b44SJordan Rupprecht#import <Foundation/Foundation.h> 2*99451b44SJordan Rupprecht 3*99451b44SJordan Rupprecht// SourceBase will be the base class of Source. We'll pass a Source object into a 4*99451b44SJordan Rupprecht// function as a SourceBase, and then see if the dynamic typing can get us through the KVO 5*99451b44SJordan Rupprecht// goo and all the way back to Source. 6*99451b44SJordan Rupprecht 7*99451b44SJordan Rupprecht@interface SourceBase: NSObject 8*99451b44SJordan Rupprecht{ 9*99451b44SJordan Rupprecht uint32_t _value; 10*99451b44SJordan Rupprecht} 11*99451b44SJordan Rupprecht- (SourceBase *) init; 12*99451b44SJordan Rupprecht- (uint32_t) getValue; 13*99451b44SJordan Rupprecht@end 14*99451b44SJordan Rupprecht 15*99451b44SJordan Rupprecht@implementation SourceBase 16*99451b44SJordan Rupprecht- (SourceBase *) init 17*99451b44SJordan Rupprecht{ 18*99451b44SJordan Rupprecht [super init]; 19*99451b44SJordan Rupprecht _value = 10; 20*99451b44SJordan Rupprecht return self; 21*99451b44SJordan Rupprecht} 22*99451b44SJordan Rupprecht- (uint32_t) getValue 23*99451b44SJordan Rupprecht{ 24*99451b44SJordan Rupprecht return _value; 25*99451b44SJordan Rupprecht} 26*99451b44SJordan Rupprecht@end 27*99451b44SJordan Rupprecht 28*99451b44SJordan Rupprecht// Source is a class that will be observed by the Observer class below. 29*99451b44SJordan Rupprecht// When Observer sets itself up to observe this property (in initWithASource) 30*99451b44SJordan Rupprecht// the KVO system will overwrite the "isa" pointer of the object with the "kvo'ed" 31*99451b44SJordan Rupprecht// one. 32*99451b44SJordan Rupprecht 33*99451b44SJordan Rupprecht@interface Source : SourceBase 34*99451b44SJordan Rupprecht{ 35*99451b44SJordan Rupprecht int _property; 36*99451b44SJordan Rupprecht} 37*99451b44SJordan Rupprecht- (Source *) init; 38*99451b44SJordan Rupprecht- (void) setProperty: (int) newValue; 39*99451b44SJordan Rupprecht@end 40*99451b44SJordan Rupprecht 41*99451b44SJordan Rupprecht@implementation Source 42*99451b44SJordan Rupprecht- (Source *) init 43*99451b44SJordan Rupprecht{ 44*99451b44SJordan Rupprecht [super init]; 45*99451b44SJordan Rupprecht _property = 20; 46*99451b44SJordan Rupprecht return self; 47*99451b44SJordan Rupprecht} 48*99451b44SJordan Rupprecht- (void) setProperty: (int) newValue 49*99451b44SJordan Rupprecht{ 50*99451b44SJordan Rupprecht _property = newValue; // This is the line in setProperty, make sure we step to here. 51*99451b44SJordan Rupprecht} 52*99451b44SJordan Rupprecht@end 53*99451b44SJordan Rupprecht 54*99451b44SJordan Rupprecht@interface SourceDerived : Source 55*99451b44SJordan Rupprecht{ 56*99451b44SJordan Rupprecht int _derivedValue; 57*99451b44SJordan Rupprecht} 58*99451b44SJordan Rupprecht- (SourceDerived *) init; 59*99451b44SJordan Rupprecht- (uint32_t) getValue; 60*99451b44SJordan Rupprecht@end 61*99451b44SJordan Rupprecht 62*99451b44SJordan Rupprecht@implementation SourceDerived 63*99451b44SJordan Rupprecht- (SourceDerived *) init 64*99451b44SJordan Rupprecht{ 65*99451b44SJordan Rupprecht [super init]; 66*99451b44SJordan Rupprecht _derivedValue = 30; 67*99451b44SJordan Rupprecht return self; 68*99451b44SJordan Rupprecht} 69*99451b44SJordan Rupprecht- (uint32_t) getValue 70*99451b44SJordan Rupprecht{ 71*99451b44SJordan Rupprecht return _derivedValue; 72*99451b44SJordan Rupprecht} 73*99451b44SJordan Rupprecht@end 74*99451b44SJordan Rupprecht 75*99451b44SJordan Rupprecht// Observer is the object that will watch Source and cause KVO to swizzle it... 76*99451b44SJordan Rupprecht 77*99451b44SJordan Rupprecht@interface Observer : NSObject 78*99451b44SJordan Rupprecht{ 79*99451b44SJordan Rupprecht Source *_source; 80*99451b44SJordan Rupprecht} 81*99451b44SJordan Rupprecht+ (Observer *) observerWithSource: (Source *) source; 82*99451b44SJordan Rupprecht- (Observer *) initWithASource: (Source *) source; 83*99451b44SJordan Rupprecht- (void) observeValueForKeyPath: (NSString *) path 84*99451b44SJordan Rupprecht ofObject: (id) object 85*99451b44SJordan Rupprecht change: (NSDictionary *) change 86*99451b44SJordan Rupprecht context: (void *) context; 87*99451b44SJordan Rupprecht@end 88*99451b44SJordan Rupprecht 89*99451b44SJordan Rupprecht@implementation Observer 90*99451b44SJordan Rupprecht 91*99451b44SJordan Rupprecht+ (Observer *) observerWithSource: (Source *) inSource; 92*99451b44SJordan Rupprecht{ 93*99451b44SJordan Rupprecht Observer *retval; 94*99451b44SJordan Rupprecht 95*99451b44SJordan Rupprecht retval = [[Observer alloc] initWithASource: inSource]; 96*99451b44SJordan Rupprecht return retval; 97*99451b44SJordan Rupprecht} 98*99451b44SJordan Rupprecht 99*99451b44SJordan Rupprecht- (Observer *) initWithASource: (Source *) source 100*99451b44SJordan Rupprecht{ 101*99451b44SJordan Rupprecht [super init]; 102*99451b44SJordan Rupprecht _source = source; 103*99451b44SJordan Rupprecht [_source addObserver: self 104*99451b44SJordan Rupprecht forKeyPath: @"property" 105*99451b44SJordan Rupprecht options: (NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) 106*99451b44SJordan Rupprecht context: NULL]; 107*99451b44SJordan Rupprecht return self; 108*99451b44SJordan Rupprecht} 109*99451b44SJordan Rupprecht 110*99451b44SJordan Rupprecht- (void) observeValueForKeyPath: (NSString *) path 111*99451b44SJordan Rupprecht ofObject: (id) object 112*99451b44SJordan Rupprecht change: (NSDictionary *) change 113*99451b44SJordan Rupprecht context: (void *) context 114*99451b44SJordan Rupprecht{ 115*99451b44SJordan Rupprecht printf ("Observer function called.\n"); 116*99451b44SJordan Rupprecht return; 117*99451b44SJordan Rupprecht} 118*99451b44SJordan Rupprecht@end 119*99451b44SJordan Rupprecht 120*99451b44SJordan Rupprechtuint32_t 121*99451b44SJordan Rupprechthandle_SourceBase (SourceBase *object) 122*99451b44SJordan Rupprecht{ 123*99451b44SJordan Rupprecht return [object getValue]; // Break here to check dynamic values. 124*99451b44SJordan Rupprecht} 125*99451b44SJordan Rupprecht 126*99451b44SJordan Rupprechtint main () 127*99451b44SJordan Rupprecht{ 128*99451b44SJordan Rupprecht Source *mySource; 129*99451b44SJordan Rupprecht Observer *myObserver; 130*99451b44SJordan Rupprecht 131*99451b44SJordan Rupprecht NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 132*99451b44SJordan Rupprecht 133*99451b44SJordan Rupprecht mySource = [[SourceDerived alloc] init]; 134*99451b44SJordan Rupprecht myObserver = [Observer observerWithSource: mySource]; 135*99451b44SJordan Rupprecht 136*99451b44SJordan Rupprecht [mySource setProperty: 5]; // Break here to see if we can step into real method. 137*99451b44SJordan Rupprecht 138*99451b44SJordan Rupprecht uint32_t return_value = handle_SourceBase (mySource); 139*99451b44SJordan Rupprecht 140*99451b44SJordan Rupprecht SourceDerived *unwatchedSource = [[SourceDerived alloc] init]; 141*99451b44SJordan Rupprecht 142*99451b44SJordan Rupprecht return_value = handle_SourceBase (unwatchedSource); 143*99451b44SJordan Rupprecht 144*99451b44SJordan Rupprecht [pool release]; 145*99451b44SJordan Rupprecht return 0; 146*99451b44SJordan Rupprecht 147*99451b44SJordan Rupprecht} 148