34 + (BOOL)accessInstanceVariablesDirectly
41 var theClass = [
self class],
43 accessors = theClass[CPObjectAccessorsForClassKey];
46 accessors = theClass[CPObjectAccessorsForClassKey] = { };
48 if (accessors.hasOwnProperty(aKey))
49 accessor = accessors[aKey];
54 capitalizedKey = aKey.charAt(0).toUpperCase() + aKey.substr(1),
60 if ([theClass instancesRespondToSelector:
string = sel_getUid(
"get" + capitalizedKey)] ||
61 [theClass instancesRespondToSelector:
string = sel_getUid(aKey)] ||
62 [theClass instancesRespondToSelector:
string = sel_getUid((isKey =
"is" + capitalizedKey))] ||
64 [theClass instancesRespondToSelector:
string = sel_getUid(
"_get" + capitalizedKey)] ||
66 [theClass instancesRespondToSelector:
string = sel_getUid((underscoreKey =
"_" + aKey))] ||
68 [theClass instancesRespondToSelector:
string = sel_getUid(
"_" + isKey)])
69 accessor = accessors[aKey] = [0, string];
71 else if ([theClass instancesRespondToSelector:sel_getUid(
"countOf" + capitalizedKey)])
75 if ([theClass instancesRespondToSelector:sel_getUid(
"objectIn" + capitalizedKey +
"AtIndex:")] ||
76 [theClass instancesRespondToSelector:sel_getUid(aKey +
"AtIndexes:")])
77 accessor = accessors[aKey] = [1];
81 else if ([theClass instancesRespondToSelector:sel_getUid(
"enumeratorOf" + capitalizedKey)] &&
82 [theClass instancesRespondToSelector:sel_getUid(
"memberOf" + capitalizedKey +
":")])
83 accessor = accessors[aKey] = [2];
89 if (class_getInstanceVariable(theClass,
string = underscoreKey) ||
90 class_getInstanceVariable(theClass,
string =
"_" + isKey) ||
91 class_getInstanceVariable(theClass,
string = aKey) ||
92 class_getInstanceVariable(theClass,
string = isKey))
93 accessor = accessors[aKey] = [3, string];
97 accessor = accessors[aKey] = [];
103 case 0:
return objj_msgSend(
self, accessor[1]);
105 case 1:
return [[_CPKeyValueCodingArray alloc] initWithTarget:self key:aKey];
107 case 2:
return [[_CPKeyValueCodingSet alloc] initWithTarget:self key:aKey];
108 case 3:
if ([theClass accessInstanceVariablesDirectly])
109 return self[accessor[1]];
117 var firstDotIndex = aKeyPath.indexOf(
".");
122 var firstKeyComponent = aKeyPath.substring(0, firstDotIndex),
123 remainingKeyPath = aKeyPath.substring(firstDotIndex + 1),
126 return [value valueForKeyPath:remainingKeyPath];
135 for (; index < count; ++index)
137 var key = keys[index],
141 [dictionary setObject:[
CPNull null] forKey:key];
144 [dictionary setObject:value forKey:key];
153 reason:[
self _objectDescription] + " is not key value coding-compliant for the key " + aKey
157 - (void)setValue:(
id)aValue forKeyPath:(
CPString)aKeyPath
162 var firstDotIndex = aKeyPath.indexOf(
".");
167 var firstKeyComponent = aKeyPath.substring(0, firstDotIndex),
168 remainingKeyPath = aKeyPath.substring(firstDotIndex + 1),
171 return [value setValue:aValue forKeyPath:remainingKeyPath];
176 var theClass = [
self class],
178 modifiers = theClass[CPObjectModifiersForClassKey];
181 modifiers = theClass[CPObjectModifiersForClassKey] = { };
183 if (modifiers.hasOwnProperty(aKey))
184 modifier = modifiers[aKey];
189 capitalizedKey = aKey.charAt(0).toUpperCase() + aKey.substr(1),
192 if ([theClass instancesRespondToSelector:
string = sel_getUid(
"set" + capitalizedKey +
":")] ||
194 [theClass instancesRespondToSelector:
string = sel_getUid(
"_set" + capitalizedKey +
":")])
195 modifier = modifiers[aKey] = [0, string];
197 else if (class_getInstanceVariable(theClass,
string =
"_" + aKey) ||
198 class_getInstanceVariable(theClass,
string =
"_" + (isKey =
"is" + capitalizedKey)) ||
199 class_getInstanceVariable(theClass,
string = aKey) ||
200 class_getInstanceVariable(theClass,
string = isKey))
201 modifier = modifiers[aKey] = [1, string];
204 modifier = modifiers[aKey] = [];
209 case 0:
return objj_msgSend(
self, modifier[1], aValue);
211 case 1:
if ([theClass accessInstanceVariablesDirectly])
215 self[modifier[1]] = aValue;
231 while ((key = [keyEnumerator nextObject]) !== nil)
235 if (value === [
CPNull null])
243 - (void)setValue:(
id)aValue forUndefinedKey:(
CPString)aKey
246 reason:[
self _objectDescription] + " is not key value coding-compliant for the key " + aKey
252 return "<" + [self className] + " 0x" + [
CPString stringWithHash:[self UID]] + ">";
261 if ([aKey hasPrefix:
@"@"])
262 return [super valueForKey:aKey.substr(1)];
264 return [self objectForKey:aKey];
267 - (void)setValue:(id)aValue forKey:(CPString)aKey
270 [self setObject:aValue forKey:aKey];
273 [self removeObjectForKey:aKey];
278 @implementation CPNull (CPKeyValueCoding)
280 - (id)valueForKey:(CPString)aKey
287 @implementation _CPKeyValueCodingArray : CPArray
291 SEL _countOfSelector;
292 SEL _objectInAtIndexSelector;
293 SEL _atIndexesSelector;
296 - (id)initWithTarget:(id)aTarget key:(CPString)aKey
302 var capitalizedKey = aKey.charAt(0).toUpperCase() + aKey.substr(1);
306 _countOfSelector = CPSelectorFromString("countOf" + capitalizedKey);
308 _objectInAtIndexSelector = CPSelectorFromString("objectIn" + capitalizedKey + "AtIndex:");
310 if (![_target respondsToSelector:_objectInAtIndexSelector])
311 _objectInAtIndexSelector = nil;
313 _atIndexesSelector = CPSelectorFromString(aKey + "AtIndexes:");
315 if (![_target respondsToSelector:_atIndexesSelector])
316 _atIndexesSelector = nil;
324 return objj_msgSend(_target, _countOfSelector);
327 - (id)objectAtIndex:(CPUInteger)anIndex
329 if (_objectInAtIndexSelector)
330 return objj_msgSend(_target, _objectInAtIndexSelector, anIndex);
332 return objj_msgSend(_target, _atIndexesSelector, [CPIndexSet indexSetWithIndex:anIndex])[0];
335 - (CPArray)objectsAtIndexes:(CPIndexSet)indexes
337 if (_atIndexesSelector)
338 return objj_msgSend(_target, _atIndexesSelector, indexes);
340 return [super objectsAtIndexes:indexes];
343 - (Class)classForCoder
345 return [CPArray class];
350 // We do this to ensure we return a CPArray.
351 return [CPArray arrayWithArray:self];
356 @implementation _CPKeyValueCodingSet : CPSet
360 SEL _countOfSelector;
361 SEL _enumeratorOfSelector;
362 SEL _memberOfSelector;
365 // This allows things like setByAddingObject: to work (since they use [[self class] alloc] internally).
366 - (id)initWithObjects:(CPArray)objects count:(CPUInteger)aCount
368 return [[CPSet alloc] initWithObjects:objects count:aCount];
371 - (id)initWithTarget:(id)aTarget key:(CPString)aKey
373 self = [super initWithObjects:nil count:0];
377 var capitalizedKey = aKey.charAt(0).toUpperCase() + aKey.substr(1);
381 _countOfSelector = CPSelectorFromString("countOf" + capitalizedKey);
382 _enumeratorOfSelector = CPSelectorFromString("enumeratorOf" + capitalizedKey);
383 _memberOfSelector = CPSelectorFromString("memberOf" + capitalizedKey + ":");
391 return objj_msgSend(_target, _countOfSelector);
394 - (CPEnumerator)objectEnumerator
396 return objj_msgSend(_target, _enumeratorOfSelector);
399 - (id)member:(id)anObject
401 return objj_msgSend(_target, _memberOfSelector, anObject);
404 - (Class)classForCoder
406 return [CPSet class];
411 // We do this to ensure we return a CPSet.
412 return [CPSet setWithSet:self];