33 if (!
self._willChangeMessageCounter)
34 self._willChangeMessageCounter =
new Object();
36 if (!
self._willChangeMessageCounter[aKey])
37 self._willChangeMessageCounter[aKey] = 1;
39 self._willChangeMessageCounter[aKey] += 1;
50 if (
self._willChangeMessageCounter &&
self._willChangeMessageCounter[aKey])
52 self._willChangeMessageCounter[aKey] -= 1;
54 if (!
self._willChangeMessageCounter[aKey])
55 delete self._willChangeMessageCounter[aKey];
58 [
CPException raise:@"CPKeyValueObservingException"
reason:@"'didChange...' message called without prior call of 'willChange...'"];
62 - (void)willChange:(CPKeyValueChange)aChange valuesAtIndexes:(
CPIndexSet)indexes forKey:(
CPString)aKey
69 if (!
self._willChangeMessageCounter)
70 self._willChangeMessageCounter =
new Object();
72 if (!
self._willChangeMessageCounter[aKey])
73 self._willChangeMessageCounter[aKey] = 1;
75 self._willChangeMessageCounter[aKey] += 1;
79 - (void)didChange:(CPKeyValueChange)aChange valuesAtIndexes:(
CPIndexSet)indexes forKey:(
CPString)aKey
86 if (
self._willChangeMessageCounter &&
self._willChangeMessageCounter[aKey])
88 self._willChangeMessageCounter[aKey] -= 1;
90 if (!
self._willChangeMessageCounter[aKey])
91 delete self._willChangeMessageCounter[aKey];
94 [
CPException raise:@"CPKeyValueObservingException"
reason:@"'didChange...' message called without prior call of 'willChange...'"];
98 - (void)willChangeValueForKey:(
CPString)aKey withSetMutation:(CPKeyValueSetMutationKind)aMutationKind usingObjects:(
CPSet)objects
105 if (!
self._willChangeMessageCounter)
106 self._willChangeMessageCounter =
new Object();
108 if (!
self._willChangeMessageCounter[aKey])
109 self._willChangeMessageCounter[aKey] = 1;
111 self._willChangeMessageCounter[aKey] += 1;
115 - (void)didChangeValueForKey:(
CPString)aKey withSetMutation:(CPKeyValueSetMutationKind)aMutationKind usingObjects:(
CPSet)objects
119 if (
self._willChangeMessageCounter &&
self._willChangeMessageCounter[aKey])
121 self._willChangeMessageCounter[aKey] -= 1;
123 if (!
self._willChangeMessageCounter[aKey])
124 delete self._willChangeMessageCounter[aKey];
127 [
CPException raise:@"CPKeyValueObservingException"
reason:@"'didChange...' message called without prior call of 'willChange...'"];
131 - (void)addObserver:(
id)anObserver forKeyPath:(
CPString)aPath options:(
unsigned)options context:(
id)aContext
133 if (!anObserver || !aPath)
136 [[_CPKVOProxy proxyForObject:self] _addObserver:anObserver forKeyPath:aPath options:options context:aContext];
139 - (void)removeObserver:(
id)anObserver forKeyPath:(
CPString)aPath
141 if (!anObserver || !aPath)
144 [
self[KVOProxyKey] _removeObserver:anObserver forKeyPath:aPath];
157 + (BOOL)automaticallyNotifiesObserversForKey:(
CPString)aKey
159 var capitalizedKey = aKey.charAt(0).toUpperCase() + aKey.substring(1),
160 selector =
"automaticallyNotifiesObserversOf" + capitalizedKey;
162 if ([[
self class] respondsToSelector:selector])
163 return objj_msgSend([
self class], selector);
170 var capitalizedKey = aKey.charAt(0).toUpperCase() + aKey.substring(1),
171 selector =
"keyPathsForValuesAffecting" + capitalizedKey;
173 if ([[
self class] respondsToSelector:selector])
174 return objj_msgSend([
self class], selector);
181 var changeKind = [aChange
objectForKey:CPKeyValueChangeKindKey],
182 oldValue = [aChange
objectForKey:CPKeyValueChangeOldKey],
183 newValue = [aChange
objectForKey:CPKeyValueChangeNewKey];
185 if (newValue === [
CPNull null])
191 var indexes = [aChange
objectForKey:CPKeyValueChangeIndexesKey];
225 changeKind = [
self objectForKey:CPKeyValueChangeKindKey];
231 forKey:CPKeyValueChangeNewKey];
235 forKey:CPKeyValueChangeOldKey];
242 forKey:CPKeyValueChangeKindKey];
246 forKey:CPKeyValueChangeOldKey];
255 forKey:CPKeyValueChangeKindKey];
259 forKey:CPKeyValueChangeNewKey];
264 return inverseChangeDictionary;
295 _CPKeyValueChangeSetMutationObjectsKey =
@"_CPKeyValueChangeSetMutationObjectsKey";
296 _CPKeyValueChangeSetMutationKindKey =
@"_CPKeyValueChangeSetMutationKindKey";
297 _CPKeyValueChangeSetMutationNewValueKey =
@"_CPKeyValueChangeSetMutationNewValueKey";
299 var _changeKindForSetMutationKind =
function(mutationKind)
301 switch (mutationKind)
317 @implementation _CPKVOProxy :
CPObject
323 Object _observersForKey;
324 int _observersForKeyLength;
328 + (id)proxyForObject:(
CPObject)anObject
330 var proxy = anObject[KVOProxyKey];
335 return [[
self alloc] initWithTarget:anObject];
338 - (id)initWithTarget:(
id)aTarget
340 if (
self = [super init])
342 _targetObject = aTarget;
343 _nativeClass = [aTarget class];
344 _observersForKey = {};
347 _observersForKeyLength = 0;
349 [
self _replaceClass];
350 aTarget[KVOProxyKey] =
self;
355 - (void)_replaceClass
357 var currentClass = _nativeClass,
358 kvoClassName =
"$KVO_" + class_getName(_nativeClass),
359 existingKVOClass = objj_lookUpClass(kvoClassName);
361 if (existingKVOClass)
363 _targetObject.isa = existingKVOClass;
364 _replacedKeys = existingKVOClass._replacedKeys;
368 var kvoClass = objj_allocateClassPair(currentClass, kvoClassName);
370 objj_registerClassPair(kvoClass);
373 kvoClass._replacedKeys = _replacedKeys;
376 var methods = class_copyMethodList(_CPKVOModelSubclass);
379 methods = methods.concat(class_copyMethodList(_CPKVOModelDictionarySubclass));
381 class_addMethods(kvoClass, methods);
383 _targetObject.isa = kvoClass;
386 - (void)_replaceModifiersForKey:(
CPString)aKey
388 if ([_replacedKeys containsObject:aKey] || ![_nativeClass automaticallyNotifiesObserversForKey:aKey])
391 [_replacedKeys addObject:aKey];
393 var theClass = _nativeClass,
394 KVOClass = _targetObject.isa,
395 capitalizedKey = aKey.charAt(0).toUpperCase() + aKey.substring(1);
398 var setKey_selector = sel_getUid(
"set" + capitalizedKey +
":"),
399 setKey_method = class_getInstanceMethod(theClass, setKey_selector);
403 var setKey_method_imp = setKey_method.method_imp;
405 class_addMethod(KVOClass, setKey_selector,
function(
self, _cmd, anObject)
407 [
self willChangeValueForKey:aKey];
409 setKey_method_imp(
self, _cmd, anObject);
411 [
self didChangeValueForKey:aKey];
416 var _setKey_selector = sel_getUid(
"_set" + capitalizedKey +
":"),
417 _setKey_method = class_getInstanceMethod(theClass, _setKey_selector);
421 var _setKey_method_imp = _setKey_method.method_imp;
423 class_addMethod(KVOClass, _setKey_selector,
function(
self, _cmd, anObject)
425 [
self willChangeValueForKey:aKey];
427 _setKey_method_imp(
self, _cmd, anObject);
429 [
self didChangeValueForKey:aKey];
434 var insertObject_inKeyAtIndex_selector = sel_getUid(
"insertObject:in" + capitalizedKey +
"AtIndex:"),
435 insertObject_inKeyAtIndex_method =
436 class_getInstanceMethod(theClass, insertObject_inKeyAtIndex_selector),
438 insertKey_atIndexes_selector = sel_getUid(
"insert" + capitalizedKey +
":atIndexes:"),
439 insertKey_atIndexes_method =
440 class_getInstanceMethod(theClass, insertKey_atIndexes_selector),
442 removeObjectFromKeyAtIndex_selector = sel_getUid(
"removeObjectFrom" + capitalizedKey +
"AtIndex:"),
443 removeObjectFromKeyAtIndex_method =
444 class_getInstanceMethod(theClass, removeObjectFromKeyAtIndex_selector),
446 removeKeyAtIndexes_selector = sel_getUid(
"remove" + capitalizedKey +
"AtIndexes:"),
447 removeKeyAtIndexes_method = class_getInstanceMethod(theClass, removeKeyAtIndexes_selector);
449 if ((insertObject_inKeyAtIndex_method || insertKey_atIndexes_method) &&
450 (removeObjectFromKeyAtIndex_method || removeKeyAtIndexes_method))
452 if (insertObject_inKeyAtIndex_method)
454 var insertObject_inKeyAtIndex_method_imp = insertObject_inKeyAtIndex_method.method_imp;
456 class_addMethod(KVOClass, insertObject_inKeyAtIndex_selector,
function(
self, _cmd, anObject, anIndex)
458 [
self willChange:CPKeyValueChangeInsertion
462 insertObject_inKeyAtIndex_method_imp(
self, _cmd, anObject, anIndex);
464 [
self didChange:CPKeyValueChangeInsertion
470 if (insertKey_atIndexes_method)
472 var insertKey_atIndexes_method_imp = insertKey_atIndexes_method.method_imp;
474 class_addMethod(KVOClass, insertKey_atIndexes_selector,
function(
self, _cmd, objects, indexes)
476 [
self willChange:CPKeyValueChangeInsertion
477 valuesAtIndexes:[indexes
copy]
480 insertKey_atIndexes_method_imp(
self, _cmd, objects, indexes);
482 [
self didChange:CPKeyValueChangeInsertion
483 valuesAtIndexes:[indexes
copy]
488 if (removeObjectFromKeyAtIndex_method)
490 var removeObjectFromKeyAtIndex_method_imp = removeObjectFromKeyAtIndex_method.method_imp;
492 class_addMethod(KVOClass, removeObjectFromKeyAtIndex_selector,
function(
self, _cmd, anIndex)
494 [
self willChange:CPKeyValueChangeRemoval
498 removeObjectFromKeyAtIndex_method_imp(
self, _cmd, anIndex);
500 [
self didChange:CPKeyValueChangeRemoval
506 if (removeKeyAtIndexes_method)
508 var removeKeyAtIndexes_method_imp = removeKeyAtIndexes_method.method_imp;
510 class_addMethod(KVOClass, removeKeyAtIndexes_selector,
function(
self, _cmd, indexes)
512 [
self willChange:CPKeyValueChangeRemoval
513 valuesAtIndexes:[indexes
copy]
516 removeKeyAtIndexes_method_imp(
self, _cmd, indexes);
518 [
self didChange:CPKeyValueChangeRemoval
519 valuesAtIndexes:[indexes
copy]
525 var replaceObjectInKeyAtIndex_withObject_selector =
526 sel_getUid(
"replaceObjectIn" + capitalizedKey +
"AtIndex:withObject:"),
527 replaceObjectInKeyAtIndex_withObject_method =
528 class_getInstanceMethod(theClass, replaceObjectInKeyAtIndex_withObject_selector);
530 if (replaceObjectInKeyAtIndex_withObject_method)
532 var replaceObjectInKeyAtIndex_withObject_method_imp =
533 replaceObjectInKeyAtIndex_withObject_method.method_imp;
535 class_addMethod(KVOClass, replaceObjectInKeyAtIndex_withObject_selector,
536 function(
self, _cmd, anIndex, anObject)
538 [
self willChange:CPKeyValueChangeReplacement
542 replaceObjectInKeyAtIndex_withObject_method_imp(
self, _cmd, anIndex, anObject);
544 [
self didChange:CPKeyValueChangeReplacement
550 var replaceKeyAtIndexes_withKey_selector =
551 sel_getUid(
"replace" + capitalizedKey +
"AtIndexes:with" + capitalizedKey +
":"),
552 replaceKeyAtIndexes_withKey_method =
553 class_getInstanceMethod(theClass, replaceKeyAtIndexes_withKey_selector);
555 if (replaceKeyAtIndexes_withKey_method)
557 var replaceKeyAtIndexes_withKey_method_imp = replaceKeyAtIndexes_withKey_method.method_imp;
559 class_addMethod(KVOClass, replaceKeyAtIndexes_withKey_selector,
function(
self, _cmd, indexes, objects)
561 [
self willChange:CPKeyValueChangeReplacement
562 valuesAtIndexes:[indexes
copy]
565 replaceObjectInKeyAtIndex_withObject_method_imp(
self, _cmd, indexes, objects);
567 [
self didChange:CPKeyValueChangeReplacement
568 valuesAtIndexes:[indexes
copy]
575 var addKeyObject_selector = sel_getUid(
"add" + capitalizedKey +
"Object:"),
576 addKeyObject_method = class_getInstanceMethod(theClass, addKeyObject_selector),
578 addKey_selector = sel_getUid(
"add" + capitalizedKey +
":"),
579 addKey_method = class_getInstanceMethod(theClass, addKey_selector),
581 removeKeyObject_selector = sel_getUid(
"remove" + capitalizedKey +
"Object:"),
582 removeKeyObject_method = class_getInstanceMethod(theClass, removeKeyObject_selector),
584 removeKey_selector = sel_getUid(
"remove" + capitalizedKey +
":"),
585 removeKey_method = class_getInstanceMethod(theClass, removeKey_selector);
587 if ((addKeyObject_method || addKey_method) && (removeKeyObject_method || removeKey_method))
589 if (addKeyObject_method)
591 var addKeyObject_method_imp = addKeyObject_method.method_imp;
593 class_addMethod(KVOClass, addKeyObject_selector,
function(
self, _cmd, anObject)
595 [
self willChangeValueForKey:aKey
596 withSetMutation:CPKeyValueUnionSetMutation
599 addKeyObject_method_imp(
self, _cmd, anObject);
601 [
self didChangeValueForKey:aKey
602 withSetMutation:CPKeyValueUnionSetMutation
609 var addKey_method_imp = addKey_method.method_imp;
611 class_addMethod(KVOClass, addKey_selector,
function(
self, _cmd, objects)
613 [
self willChangeValueForKey:aKey
614 withSetMutation:CPKeyValueUnionSetMutation
615 usingObjects:[objects
copy]];
617 addKey_method_imp(
self, _cmd, objects);
619 [
self didChangeValueForKey:aKey
620 withSetMutation:CPKeyValueUnionSetMutation
621 usingObjects:[objects
copy]];
625 if (removeKeyObject_method)
627 var removeKeyObject_method_imp = removeKeyObject_method.method_imp;
629 class_addMethod(KVOClass, removeKeyObject_selector,
function(
self, _cmd, anObject)
631 [
self willChangeValueForKey:aKey
632 withSetMutation:CPKeyValueMinusSetMutation
635 removeKeyObject_method_imp(
self, _cmd, anObject);
637 [
self didChangeValueForKey:aKey
638 withSetMutation:CPKeyValueMinusSetMutation
643 if (removeKey_method)
645 var removeKey_method_imp = removeKey_method.method_imp;
647 class_addMethod(KVOClass, removeKey_selector,
function(
self, _cmd, objects)
649 [
self willChangeValueForKey:aKey
650 withSetMutation:CPKeyValueMinusSetMutation
651 usingObjects:[objects
copy]];
653 removeKey_method_imp(
self, _cmd, objects);
655 [
self didChangeValueForKey:aKey
656 withSetMutation:CPKeyValueMinusSetMutation
657 usingObjects:[objects
copy]];
662 var intersectKey_selector = sel_getUid(
"intersect" + capitalizedKey +
":"),
663 intersectKey_method = class_getInstanceMethod(theClass, intersectKey_selector);
665 if (intersectKey_method)
667 var intersectKey_method_imp = intersectKey_method.method_imp;
669 class_addMethod(KVOClass, intersectKey_selector,
function(
self, _cmd, aSet)
671 [
self willChangeValueForKey:aKey
672 withSetMutation:CPKeyValueIntersectSetMutation
673 usingObjects:[aSet copy]];
675 intersectKey_method_imp(
self, _cmd, aSet);
677 [
self didChangeValueForKey:aKey
678 withSetMutation:CPKeyValueIntersectSetMutation
679 usingObjects:[aSet copy]];
684 var affectingKeys = [[_nativeClass keyPathsForValuesAffectingValueForKey:aKey] allObjects],
685 affectingKeysCount = affectingKeys ? affectingKeys.length : 0;
687 if (!affectingKeysCount)
690 var dependentKeysForClass = _nativeClass[DependentKeysKey];
692 if (!dependentKeysForClass)
694 dependentKeysForClass = {};
695 _nativeClass[DependentKeysKey] = dependentKeysForClass;
698 while (affectingKeysCount--)
700 var affectingKey = affectingKeys[affectingKeysCount],
701 affectedKeys = dependentKeysForClass[affectingKey];
706 dependentKeysForClass[affectingKey] = affectedKeys;
709 [affectedKeys addObject:aKey];
714 if (affectingKey.indexOf(
@".") !== -1)
715 [_targetObject addObserver:self forKeyPath:affectingKey options:CPKeyValueObservingOptionPrior | kvoNewAndOld context:nil];
717 [
self _replaceModifiersForKey:affectingKey];
721 - (void)observeValueForKeyPath:(
CPString)theKeyPath ofObject:(
id)theObject change:(CPDictionary)theChanges context:(
id)theContext
724 var dependentKeysForClass = _nativeClass[DependentKeysKey],
725 dependantKeys = [dependentKeysForClass[theKeyPath] allObjects];
727 var isBeforeFlag = !![theChanges
objectForKey:CPKeyValueChangeNotificationIsPriorKey];
728 for (var i = 0; i < [dependantKeys count]; i++)
730 var dependantKey = [dependantKeys objectAtIndex:i];
731 [
self _sendNotificationsForKey:dependantKey changeOptions:theChanges isBefore:isBeforeFlag];
735 - (void)_addObserver:(
id)anObserver forKeyPath:(
CPString)aPath options:(
unsigned)options context:(
id)aContext
742 if (aPath.indexOf(
'.') !==
CPNotFound && aPath.charAt(0) !==
'@')
743 forwarder = [[_CPKVOForwardingObserver alloc] initWithKeyPath:aPath
object:_targetObject observer:anObserver options:options context:aContext];
745 [
self _replaceModifiersForKey:aPath];
747 var observers = _observersForKey[aPath];
752 _observersForKey[aPath] = observers;
753 _observersForKeyLength++;
756 [observers setObject:_CPKVOInfoMake(anObserver, options, aContext, forwarder) forKey:[anObserver UID]];
760 var newValue = [_targetObject valueForKeyPath:aPath];
762 if (newValue === nil || newValue === undefined)
765 var changes = [
CPDictionary dictionaryWithObject:newValue forKey:CPKeyValueChangeNewKey];
766 [anObserver observeValueForKeyPath:aPath ofObject:_targetObject change:changes context:aContext];
770 - (void)_removeObserver:(
id)anObserver forKeyPath:(
CPString)aPath
772 var observers = _observersForKey[aPath];
776 CPLog.warn(
@"Cannot remove an observer %@ for the key path \"%@\
" from %@ because it is not registered as an observer.",
777 _targetObject, aPath, anObserver);
784 var forwarder = [observers objectForKey:[anObserver UID]].forwarder;
785 [forwarder finalize];
788 [observers removeObjectForKey:[anObserver UID]];
790 if (![observers count])
792 _observersForKeyLength--;
793 delete _observersForKey[aPath];
796 if (!_observersForKeyLength)
798 _targetObject.isa = _nativeClass;
799 delete _targetObject[KVOProxyKey];
805 - (void)_sendNotificationsForKey:(
CPString)aKey changeOptions:(CPDictionary)changeOptions isBefore:(BOOL)isBefore
807 var changes = _changesForKey[aKey];
814 var level = _nestingForKey[aKey];
817 _nestingForKey[aKey] = level + 1;
821 _nestingForKey[aKey] = 1;
823 changes = changeOptions;
825 var indexes = [changes objectForKey:CPKeyValueChangeIndexesKey],
826 setMutationKind = changes[_CPKeyValueChangeSetMutationKindKey];
830 var setMutationObjects = [changes[_CPKeyValueChangeSetMutationObjectsKey] copy],
831 setExistingObjects = [[_targetObject valueForKey: aKey] copy];
835 [setExistingObjects intersectSet: setMutationObjects];
836 [changes setValue:setExistingObjects forKey:CPKeyValueChangeOldKey];
840 [setExistingObjects minusSet: setMutationObjects];
841 [changes setValue:setExistingObjects forKey:CPKeyValueChangeOldKey];
847 [setMutationObjects minusSet: setExistingObjects];
850 changes[_CPKeyValueChangeSetMutationNewValueKey] = setMutationObjects;
855 var type = [changes objectForKey:CPKeyValueChangeKindKey];
860 var newValues = [[_targetObject mutableArrayValueForKeyPath:aKey] objectsAtIndexes:indexes];
861 [changes setValue:newValues forKey:CPKeyValueChangeOldKey];
866 var oldValue = [_targetObject valueForKey:aKey];
868 if (oldValue === nil || oldValue === undefined)
871 [changes setObject:oldValue forKey:CPKeyValueChangeOldKey];
874 [changes setObject:1 forKey:CPKeyValueChangeNotificationIsPriorKey];
876 _changesForKey[aKey] = changes;
880 var level = _nestingForKey[aKey];
881 if (!changes || !level)
883 if (_targetObject._willChangeMessageCounter && _targetObject._willChangeMessageCounter[aKey])
886 _targetObject._willChangeMessageCounter[aKey] -= 1;
888 if (!_targetObject._willChangeMessageCounter[aKey])
889 delete _targetObject._willChangeMessageCounter[aKey];
894 [
CPException raise:@"CPKeyValueObservingException"
reason:@"'didChange...' message called without prior call of 'willChange...'"];
897 _nestingForKey[aKey] = level - 1;
904 delete _nestingForKey[aKey];
906 [changes removeObjectForKey:CPKeyValueChangeNotificationIsPriorKey];
908 var indexes = [changes objectForKey:CPKeyValueChangeIndexesKey],
909 setMutationKind = changes[_CPKeyValueChangeSetMutationKindKey];
915 var newValue = changes[_CPKeyValueChangeSetMutationNewValueKey];
916 [changes setValue:newValue forKey:CPKeyValueChangeNewKey];
919 delete changes[_CPKeyValueChangeSetMutationNewValueKey];
920 delete changes[_CPKeyValueChangeSetMutationObjectsKey];
921 delete changes[_CPKeyValueChangeSetMutationKindKey];
925 var type = [changes objectForKey:CPKeyValueChangeKindKey];
930 var newValues = [[_targetObject mutableArrayValueForKeyPath:aKey] objectsAtIndexes:indexes];
931 [changes setValue:newValues forKey:CPKeyValueChangeNewKey];
936 var newValue = [_targetObject valueForKey:aKey];
938 if (newValue === nil || newValue === undefined)
941 [changes setObject:newValue forKey:CPKeyValueChangeNewKey];
944 delete _changesForKey[aKey];
947 var observers = [_observersForKey[aKey] allValues],
948 count = observers ? observers.length : 0;
952 var observerInfo = observers[count];
955 [observerInfo.observer observeValueForKeyPath:aKey ofObject:_targetObject change:changes context:observerInfo.context];
958 var dependentKeysMap = _nativeClass[DependentKeysKey];
960 if (!dependentKeysMap)
963 var dependentKeyPaths = [dependentKeysMap[aKey] allObjects];
965 if (!dependentKeyPaths)
969 count = [dependentKeyPaths count];
971 for (; index < count; ++index)
973 var keyPath = dependentKeyPaths[index];
975 [
self _sendNotificationsForKey:keyPath
976 changeOptions:isBefore ? [changeOptions
copy] : _changesForKey[keyPath]
982 @implementation _CPKVOModelSubclass
987 - (void)willChangeValueForKey:(
CPString)aKey
989 var superClass = [
self class],
990 methodSelector =
@selector(willChangeValueForKey:),
991 methodImp = class_getMethodImplementation(superClass, methodSelector);
993 methodImp(
self, methodSelector, aKey);
998 var changeOptions = [
CPDictionary dictionaryWithObject:CPKeyValueChangeSetting forKey:CPKeyValueChangeKindKey];
1000 [[_CPKVOProxy proxyForObject:self] _sendNotificationsForKey:aKey changeOptions:changeOptions isBefore:YES];
1003 - (void)didChangeValueForKey:(
CPString)aKey
1005 var superClass = [
self class],
1006 methodSelector =
@selector(didChangeValueForKey:),
1007 methodImp = class_getMethodImplementation(superClass, methodSelector);
1009 methodImp(
self, methodSelector, aKey);
1014 [[_CPKVOProxy proxyForObject:self] _sendNotificationsForKey:aKey changeOptions:nil isBefore:NO];
1017 - (void)willChange:(CPKeyValueChange)change valuesAtIndexes:(
CPIndexSet)indexes forKey:(
CPString)aKey
1019 var superClass = [
self class],
1020 methodSelector =
@selector(willChange:valuesAtIndexes:forKey:),
1021 methodImp = class_getMethodImplementation(superClass, methodSelector);
1023 methodImp(
self, methodSelector, change, indexes, aKey);
1028 var changeOptions = [
CPDictionary dictionaryWithObjects:[change, indexes] forKeys:[CPKeyValueChangeKindKey, CPKeyValueChangeIndexesKey]];
1030 [[_CPKVOProxy proxyForObject:self] _sendNotificationsForKey:aKey changeOptions:changeOptions isBefore:YES];
1033 - (void)didChange:(CPKeyValueChange)change valuesAtIndexes:(
CPIndexSet)indexes forKey:(
CPString)aKey
1035 var superClass = [
self class],
1036 methodSelector =
@selector(didChange:valuesAtIndexes:forKey:),
1037 methodImp = class_getMethodImplementation(superClass, methodSelector);
1039 methodImp(
self, methodSelector, change, indexes, aKey);
1044 [[_CPKVOProxy proxyForObject:self] _sendNotificationsForKey:aKey changeOptions:nil isBefore:NO];
1047 - (void)willChangeValueForKey:(
CPString)aKey withSetMutation:(CPKeyValueSetMutationKind)mutationKind usingObjects:(
CPSet)objects
1049 var superClass = [
self class],
1050 methodSelector =
@selector(willChangeValueForKey:withSetMutation:usingObjects:),
1051 methodImp = class_getMethodImplementation(superClass, methodSelector);
1053 methodImp(
self, methodSelector, aKey, mutationKind, objects);
1058 var changeKind = _changeKindForSetMutationKind(mutationKind),
1059 changeOptions = [
CPDictionary dictionaryWithObject:changeKind forKey:CPKeyValueChangeKindKey];
1061 changeOptions[_CPKeyValueChangeSetMutationObjectsKey] = objects;
1062 changeOptions[_CPKeyValueChangeSetMutationKindKey] = mutationKind;
1064 [[_CPKVOProxy proxyForObject:self] _sendNotificationsForKey:aKey changeOptions:changeOptions isBefore:YES];
1067 - (void)didChangeValueForKey:(
CPString)aKey withSetMutation:(CPKeyValueSetMutationKind)mutationKind usingObjects:(
CPSet)objects
1069 var superClass = [
self class],
1070 methodSelector =
@selector(didChangeValueForKey:withSetMutation:usingObjects:),
1071 methodImp = class_getMethodImplementation(superClass, methodSelector);
1073 methodImp(
self, methodSelector, aKey, mutationKind, objects);
1078 [[_CPKVOProxy proxyForObject:self] _sendNotificationsForKey:aKey changeOptions:nil isBefore:NO];
1083 return self[KVOProxyKey]._nativeClass;
1088 return [[
self class] superclass];
1091 - (BOOL)isKindOfClass:(Class)aClass
1093 return [[
self class] isSubclassOfClass:aClass];
1096 - (BOOL)isMemberOfClass:(Class)aClass
1098 return [
self class] == aClass;
1103 return [
self class].name;
1107 @implementation _CPKVOModelDictionarySubclass
1112 - (void)removeAllObjects
1114 var keys = [
self allKeys],
1115 count = [keys count],
1118 for (; i < count; i++)
1119 [self willChangeValueForKey:keys[i]];
1121 var superClass = [
self class],
1122 methodSelector =
@selector(removeAllObjects),
1123 methodImp = class_getMethodImplementation(superClass, methodSelector);
1125 methodImp(
self, methodSelector);
1127 for (i = 0; i < count; i++)
1128 [self didChangeValueForKey:keys[i]];
1131 - (void)removeObjectForKey:(
id)aKey
1133 [
self willChangeValueForKey:aKey];
1135 var superClass = [
self class],
1136 methodSelector =
@selector(removeObjectForKey:),
1137 methodImp = class_getMethodImplementation(superClass, methodSelector);
1139 methodImp(
self, methodSelector, aKey);
1141 [
self didChangeValueForKey:aKey];
1144 - (void)setObject:(
id)anObject forKey:(
id)aKey
1146 [
self willChangeValueForKey:aKey];
1148 var superClass = [
self class],
1149 methodSelector =
@selector(setObject:forKey:),
1150 methodImp = class_getMethodImplementation(superClass, methodSelector);
1152 methodImp(
self, methodSelector, anObject, aKey);
1154 [
self didChangeValueForKey:aKey];
1159 @implementation _CPKVOForwardingObserver :
CPObject
1172 - (id)initWithKeyPath:(
CPString)aKeyPath object:(
id)anObject observer:(
id)anObserver options:(
unsigned)options context:(
id)aContext
1174 self = [
super init];
1176 _context = aContext;
1177 _observer = anObserver;
1181 var dotIndex = aKeyPath.indexOf(
'.');
1184 [
CPException raise:CPInvalidArgumentException
reason:"Created _CPKVOForwardingObserver without compound key path: " + aKeyPath];
1186 _firstPart = aKeyPath.substring(0, dotIndex);
1187 _secondPart = aKeyPath.substring(dotIndex + 1);
1190 [_object addObserver:self forKeyPath:_firstPart options:_options context:nil];
1193 _value = [_object valueForKey:_firstPart];
1196 [_value addObserver:self forKeyPath:_secondPart options:_options context:nil];
1201 - (void)observeValueForKeyPath:(
CPString)aKeyPath ofObject:(
id)anObject change:(CPDictionary)changes context:(
id)aContext
1203 if (aKeyPath === _firstPart)
1205 var oldValue = [_value valueForKeyPath:_secondPart],
1206 newValue = [_object valueForKeyPath:_firstPart + "." + _secondPart],
1207 pathChanges = [
CPDictionary dictionaryWithObjectsAndKeys:
1208 newValue ? newValue : [
CPNull null], CPKeyValueChangeNewKey,
1209 oldValue ? oldValue : [
CPNull null], CPKeyValueChangeOldKey,
1210 CPKeyValueChangeSetting, CPKeyValueChangeKindKey];
1212 [_observer observeValueForKeyPath:_firstPart + "." + _secondPart ofObject:_object change:pathChanges context:_context];
1216 [_value removeObserver:self forKeyPath:_secondPart];
1218 _value = [_object valueForKey:_firstPart];
1221 [_value addObserver:self forKeyPath:_secondPart options:_options context:nil];
1226 [_observer observeValueForKeyPath:_firstPart + "." + aKeyPath ofObject:_object change:changes context:_context];
1233 [_value removeObserver:self forKeyPath:_secondPart];
1235 [_object removeObserver:self forKeyPath:_firstPart];
1245 var _CPKVOInfoMake =
function _CPKVOInfoMake(anObserver, theOptions, aContext, aForwarder)
1248 observer: anObserver,
1249 options: theOptions,
1251 forwarder: aForwarder