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