Oolite 1.91.0.7604-240417-a536cbe
Loading...
Searching...
No Matches
OOWeakReference.m
Go to the documentation of this file.
1/*
2
3OOWeakReference.m
4
5Written by Jens Ayton in 2007-2013 for Oolite.
6This code is hereby placed in the public domain.
7
8*/
9
10#import "OOWeakReference.h"
11
12
13@interface OOWeakReferenceTemplates: NSObject
14
15+ (void)weakRefDrop;
17+ (id)nilMethod;
18
19@end
20
21
22@implementation OOWeakReference
23
24// *** Core functionality.
25
26+ (id)weakRefWithObject:(id<OOWeakReferenceSupport>)object
27{
28 if (object == nil) return nil;
29
30 OOWeakReference *result = [OOWeakReference alloc];
31 // No init for proxies.
32 result->_object = object;
33 return [result autorelease];
34}
35
36
37- (void)dealloc
38{
39 [_object weakRefDied:self];
40
41 [super dealloc];
42}
43
44
45- (NSString *)description
46{
47 if (_object != nil) return [_object description];
48 else return [NSString stringWithFormat:@"<Dead %@ %p>", [self class], self];
49}
50
51
53{
54 return _object;
55}
56
57
58- (id)weakRetain
59{
60 return [self retain];
61}
62
63
64- (void)weakRefDrop
65{
66 _object = nil;
67}
68
69
70// *** Proxy evilness beyond this point.
71
72- (Class) class
73{
74 return [_object class];
75}
76
77
78- (BOOL) isProxy
79{
80 return YES;
81}
82
83
84- (void)forwardInvocation:(NSInvocation *)invocation
85{
86 // Does the right thing even with nil _object.
87 [invocation invokeWithTarget:_object];
88}
89
90
91- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
92{
93 NSMethodSignature *result = nil;
94
95 if (__builtin_expect(
96 selector != @selector(weakRefDrop) &&
97 selector != @selector(weakRefUnderlyingObject), 1))
98 {
99 // Not a proxy method; get signature from _object if it exists, otherwise generic signature for nil calls.
100 if (__builtin_expect(_object != nil, 1)) result = [(id)_object methodSignatureForSelector:selector];
101 else result = [OOWeakReferenceTemplates methodSignatureForSelector:@selector(nilMethod)];
102 }
103 else
104 {
105 // One of OOWeakReference's own methods.
106 result = [OOWeakReferenceTemplates methodSignatureForSelector:selector];
107 }
108
109 return result;
110}
111
112
113- (BOOL)respondsToSelector:(SEL)selector
114{
115 if (__builtin_expect(_object != nil &&
116 selector != @selector(weakRefDrop) &&
117 selector != @selector(weakRefUnderlyingObject), 1))
118 {
119 // _object exists and it's not one of our methods, ask _object.
120 return [_object respondsToSelector:selector];
121 }
122 else
123 {
124 // Selector we responds to, or _object is nil and therefore responds to everything.
125 return YES;
126 }
127}
128
129
130// New fast forwarding mechanism introduced in Mac OS X 10.5.
131// Note that -forwardInvocation: is still called if _object is nil.
132- (id)forwardingTargetForSelector:(SEL)sel
133{
134 return _object;
135}
136
137@end
138
139
140@implementation NSObject (OOWeakReference)
141
143{
144 return self;
145}
146
147@end
148
149
150@implementation OOWeakRefObject
151
152- (id)weakRetain
153{
154 if (weakSelf == nil) weakSelf = [OOWeakReference weakRefWithObject:self];
155 return [weakSelf retain]; // Each caller releases this, as -weakRetain must be balanced with -release.
156}
157
158
159- (void)weakRefDied:(OOWeakReference *)weakRef
160{
161 if (weakRef == weakSelf) weakSelf = nil;
162}
163
164
165- (void)dealloc
166{
167 [weakSelf weakRefDrop]; // Very important!
168 [super dealloc];
169}
170
171
172- (id)weakSelf
173{
174 return [[self weakRetain] autorelease];
175}
176
177@end
178
179
180@implementation OOWeakReferenceTemplates
181
182// These are never called, but an implementation must exist so that -methodSignatureForSelector: works.
183+ (void)weakRefDrop {}
184+ (id)weakRefUnderlyingObject { return nil; }
185+ (id)nilMethod { return nil; }
186
187@end
return nil
id< OOWeakReferenceSupport > _object
NSString * description()
id weakRefWithObject:(id< OOWeakReferenceSupport > object)