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] = [];
104 return self.isa.objj_msgSend0(
self, accessor[1]);
108 return [[_CPKeyValueCodingArray alloc] initWithTarget:self key:aKey];
112 return [[_CPKeyValueCodingSet alloc] initWithTarget:self key:aKey];
115 if ([theClass accessInstanceVariablesDirectly])
116 return self[accessor[1]];
124 var firstDotIndex = aKeyPath.indexOf(
".");
129 var firstKeyComponent = aKeyPath.substring(0, firstDotIndex),
130 remainingKeyPath = aKeyPath.substring(firstDotIndex + 1),
133 return [value valueForKeyPath:remainingKeyPath];
142 for (; index < count; ++index)
144 var key = keys[index],
148 [dictionary setObject:[
CPNull null] forKey:key];
151 [dictionary setObject:value forKey:key];
160 reason:[
self _objectDescription] + " is not key value coding-compliant for the key " + aKey
161 userInfo:@{ CPTargetObjectUserInfoKey: self, CPUnknownUserInfoKey: aKey }]
raise];
164 - (void)setValue:(
id)aValue forKeyPath:(
CPString)aKeyPath
169 var firstDotIndex = aKeyPath.indexOf(
".");
174 var firstKeyComponent = aKeyPath.substring(0, firstDotIndex),
175 remainingKeyPath = aKeyPath.substring(firstDotIndex + 1),
178 return [value setValue:aValue forKeyPath:remainingKeyPath];
186 if (aValue && aValue.isa && [aValue isKindOfClass:
CPValue])
187 aValue = [aValue JSObject];
189 var theClass = [
self class],
191 modifiers = theClass[CPObjectModifiersForClassKey];
194 modifiers = theClass[CPObjectModifiersForClassKey] = { };
196 if (modifiers.hasOwnProperty(aKey))
197 modifier = modifiers[aKey];
202 capitalizedKey = aKey.charAt(0).toUpperCase() + aKey.substr(1),
205 if ([theClass instancesRespondToSelector:
string = sel_getUid(
"set" + capitalizedKey +
":")] ||
207 [theClass instancesRespondToSelector:
string = sel_getUid(
"_set" + capitalizedKey +
":")])
208 modifier = modifiers[aKey] = [0, string];
210 else if (class_getInstanceVariable(theClass,
string =
"_" + aKey) ||
211 class_getInstanceVariable(theClass,
string =
"_" + (isKey =
"is" + capitalizedKey)) ||
212 class_getInstanceVariable(theClass,
string = aKey) ||
213 class_getInstanceVariable(theClass,
string = isKey))
214 modifier = modifiers[aKey] = [1, string];
217 modifier = modifiers[aKey] = [];
222 case 0:
return self.isa.objj_msgSend1(
self, modifier[1], aValue);
224 case 1:
if ([theClass accessInstanceVariablesDirectly])
228 self[modifier[1]] = aValue;
244 while ((key = [keyEnumerator nextObject]) !== nil)
248 if (value === [
CPNull null])
256 - (void)setValue:(
id)aValue forUndefinedKey:(
CPString)aKey
259 reason:[
self _objectDescription] + " is not key value coding-compliant for the key " + aKey
260 userInfo:@{ CPTargetObjectUserInfoKey: self, CPUnknownUserInfoKey: aKey }]
raise];
265 return "<" + [self className] + " 0x" + [
CPString stringWithHash:[self UID]] + ">";
274 if ([aKey hasPrefix:
@"@"]) 275 return [super valueForKey:aKey.substr(1)]; 277 return [self objectForKey:aKey]; 280 - (void)setValue:(id)aValue forKey:(CPString)aKey 283 [self setObject:aValue forKey:aKey]; 286 [self removeObjectForKey:aKey]; 291 @implementation CPNull (CPKeyValueCoding) 293 - (id)valueForKey:(CPString)aKey 300 @implementation _CPKeyValueCodingArray : CPArray 304 SEL _countOfSelector; 305 SEL _objectInAtIndexSelector; 306 SEL _atIndexesSelector; 309 - (id)initWithTarget:(id)aTarget key:(CPString)aKey 315 var capitalizedKey = aKey.charAt(0).toUpperCase() + aKey.substr(1); 319 _countOfSelector = CPSelectorFromString("countOf" + capitalizedKey);
321 _objectInAtIndexSelector = CPSelectorFromString("objectIn" + capitalizedKey + "AtIndex:");
323 if (![_target respondsToSelector:_objectInAtIndexSelector])
324 _objectInAtIndexSelector = nil;
326 _atIndexesSelector = CPSelectorFromString(aKey + "AtIndexes:");
328 if (![_target respondsToSelector:_atIndexesSelector])
329 _atIndexesSelector = nil;
337 return _target == nil ? nil : _target.isa.objj_msgSend0(_target, _countOfSelector);
340 - (id)objectAtIndex:(CPUInteger)anIndex
342 if (_objectInAtIndexSelector)
343 return _target == nil ? nil : _target.isa.objj_msgSend1(_target, _objectInAtIndexSelector, anIndex);
345 return _target == nil ? nil : _target.isa.objj_msgSend1(_target, _atIndexesSelector, [CPIndexSet indexSetWithIndex:anIndex])[0];
348 - (CPArray)objectsAtIndexes:(CPIndexSet)indexes
350 if (_atIndexesSelector)
351 return _target == nil ? nil : _target.isa.objj_msgSend1(_target, _atIndexesSelector, indexes);
353 return [super objectsAtIndexes:indexes];
356 - (Class)classForCoder
358 return [CPArray class];
363 // We do this to ensure we return a CPArray.
364 return [CPArray arrayWithArray:self];
369 @implementation _CPKeyValueCodingSet : CPSet
373 SEL _countOfSelector;
374 SEL _enumeratorOfSelector;
375 SEL _memberOfSelector;
378 // This allows things like setByAddingObject: to work (since they use [[self class] alloc] internally).
379 - (id)initWithObjects:(CPArray)objects count:(CPUInteger)aCount
381 return [[CPSet alloc] initWithObjects:objects count:aCount];
384 - (id)initWithTarget:(id)aTarget key:(CPString)aKey
386 self = [super initWithObjects:nil count:0];
390 var capitalizedKey = aKey.charAt(0).toUpperCase() + aKey.substr(1);
394 _countOfSelector = CPSelectorFromString("countOf" + capitalizedKey);
395 _enumeratorOfSelector = CPSelectorFromString("enumeratorOf" + capitalizedKey);
396 _memberOfSelector = CPSelectorFromString("memberOf" + capitalizedKey + ":");
404 return _target == nil ? nil : _target.isa.objj_msgSend0(_target, _countOfSelector);
407 - (CPEnumerator)objectEnumerator
409 return _target == nil ? nil : _target.isa.objj_msgSend0(_target, _enumeratorOfSelector);
412 - (id)member:(id)anObject
414 return _target == nil ? nil : _target.isa.objj_msgSend1(_target, _memberOfSelector, anObject);
417 - (Class)classForCoder
419 return [CPSet class];
424 // We do this to ensure we return a CPSet.
425 return [CPSet setWithSet:self];
Used to implement exception handling (creating & raising).
var CPObjectAccessorsForClassKey
void willChangeValueForKey:(CPString aKey)
var CPObjectModifiersForClassKey
An object representation of nil.
void setValue:forUndefinedKey:(id aValue, [forUndefinedKey] CPString aKey)
CPEnumerator keyEnumerator()
A mutable key-value pair collection.
A generic "value". Can be subclassed to hold specific data types.
An immutable string (collection of characters).
id objectForKey:(id aKey)
id valueForKey:(CPString aKey)
void didChangeValueForKey:(CPString aKey)
CPTargetObjectUserInfoKey
id valueForUndefinedKey:(CPString aKey)
void setValue:forKey:(id aValue, [forKey] CPString aKey)
CPException exceptionWithName:reason:userInfo:(CPString aName, [reason] CPString aReason, [userInfo] CPDictionary aUserInfo)