mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 09:04:13 +00:00
NSKVOSupport: Implement legacy KVO API
Implements the setKeys:triggerChangeNotificationsForDependentKey: class method. Please do not use it. It is fundamentally broken, and requires the object's meta class to hold additional state. Keys from this class method are the last resort when retrieving dependencies via keyPathsForValuesAffectingValueForKey:. This aligns with the implementation in Foundation.
This commit is contained in:
parent
732fd2d2fb
commit
8889e7ed81
1 changed files with 35 additions and 0 deletions
|
@ -569,9 +569,29 @@ _removeKeypathObserver(id object, NSString *keypath, id observer, void *context)
|
|||
|
||||
#pragma region KVO Core Implementation - NSObject category
|
||||
|
||||
static const char *const KVO_MAP = "_NSKVOMap";
|
||||
|
||||
@implementation
|
||||
NSObject (NSKeyValueObserving)
|
||||
|
||||
+ (void) setKeys: (NSArray *) triggerKeys
|
||||
triggerChangeNotificationsForDependentKey: (NSString *) dependentKey
|
||||
{
|
||||
NSMutableDictionary<NSString *, NSSet *> *affectingKeys;
|
||||
NSSet *triggerKeySet;
|
||||
|
||||
affectingKeys = objc_getAssociatedObject(self, KVO_MAP);
|
||||
if (nil == affectingKeys)
|
||||
{
|
||||
affectingKeys = [NSMutableDictionary dictionaryWithCapacity: 10];
|
||||
objc_setAssociatedObject(self, KVO_MAP, affectingKeys,
|
||||
OBJC_ASSOCIATION_RETAIN);
|
||||
}
|
||||
|
||||
triggerKeySet = [NSSet setWithArray: triggerKeys];
|
||||
[affectingKeys setValue: triggerKeySet forKey: dependentKey];
|
||||
}
|
||||
|
||||
- (void) observeValueForKeyPath: (NSString *)keyPath
|
||||
ofObject: (id)object
|
||||
change: (NSDictionary<NSString *, id> *)change
|
||||
|
@ -631,6 +651,7 @@ static void *s_kvoObservationInfoAssociationKey; // has no value; pointer used
|
|||
static NSSet *emptySet = nil;
|
||||
static gs_mutex_t lock = GS_MUTEX_INIT_STATIC;
|
||||
NSUInteger keyLength;
|
||||
NSDictionary *affectingKeys;
|
||||
|
||||
if (nil == emptySet)
|
||||
{
|
||||
|
@ -701,6 +722,20 @@ static void *s_kvoObservationInfoAssociationKey; // has no value; pointer used
|
|||
{
|
||||
return [self performSelector:sel];
|
||||
}
|
||||
|
||||
// We compute an NSSet from information provided by previous invocations
|
||||
// of the now-deprecated setKeys:triggerChangeNotificationsForDependentKey:
|
||||
// if the original imp returns an empty set.
|
||||
// This aligns with Apple's backwards compatibility.
|
||||
affectingKeys = (NSDictionary *)objc_getAssociatedObject(self, KVO_MAP);
|
||||
if (unlikely(nil != affectingKeys))
|
||||
{
|
||||
NSSet *set = [affectingKeys objectForKey:key];
|
||||
if (set != nil)
|
||||
{
|
||||
return set;
|
||||
}
|
||||
}
|
||||
}
|
||||
return emptySet;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue