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
| #import <Foundation/Foundation.h>
#include <stdio.h>
struct return_me
{
int first;
int second;
};
@interface SourceBase: NSObject
{
struct return_me my_return;
}
- (SourceBase *) initWithFirst: (int) first andSecond: (int) second;
- (void) randomMethod;
- (struct return_me) returnsStruct;
@end
@implementation SourceBase
- (void) randomMethod
{
printf ("Called in SourceBase version of randomMethod.\n"); // SourceBase randomMethod start line.
}
- (struct return_me) returnsStruct
{
return my_return; // SourceBase returnsStruct start line.
}
- (SourceBase *) initWithFirst: (int) first andSecond: (int) second
{
my_return.first = first;
my_return.second = second;
return self;
}
@end
@interface Source : SourceBase
{
int _property;
}
- (void) setProperty: (int) newValue;
- (void) randomMethod;
- (struct return_me) returnsStruct;
@end
@implementation Source
- (void) setProperty: (int) newValue
{
_property = newValue;
}
- (void) randomMethod
{
[super randomMethod]; // Source randomMethod start line.
printf ("Called in Source version of random method.");
}
- (struct return_me) returnsStruct
{
printf ("Called in Source version of returnsStruct.\n"); // Source returnsStruct start line.
return [super returnsStruct]; // Source returnsStruct call line.
}
@end
@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
int main ()
{
Source *mySource;
Observer *myObserver;
struct return_me ret_val;
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
mySource = [[Source alloc] init];
[mySource randomMethod]; // Set first breakpoint here.
ret_val = [mySource returnsStruct]; // Set second breakpoint here.
myObserver = [Observer observerWithSource: mySource];
[mySource randomMethod]; // Set third breakpoint here.
ret_val = [mySource returnsStruct]; // Set fourth breakpoint here.
[mySource setProperty: 5]; // Set fifth breakpoint here.
// We also had a bug where stepping into a method dispatch to nil turned
// into continue. So make sure that works here:
mySource = nil;
[mySource randomMethod]; // Set nil step breakpoint here.
[pool release]; // Step over nil should stop here.
return 0;
}
|