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