xref: /llvm-project/lldb/test/API/lang/objc/objc-dynamic-value/dynamic-value.m (revision 99451b4453688a94c6014cac233d371ab4cc342d)
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