mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-20 20:26:42 +00:00
Avoid calling depreceted methods just because KVO has overridden them.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@26170 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
d429949533
commit
04d03bff35
3 changed files with 102 additions and 50 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
2008-03-02 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* Source/NSKeyValueCoding.m: Avoid calling deprecated methods as a
|
||||||
|
result of KVO overriding them.
|
||||||
|
* Source/NSKeyValueObserving.m: Minor tidyups
|
||||||
|
|
||||||
2008-02-25 Richard Frith-Macdonald <rfm@gnu.org>
|
2008-02-25 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Headers/Foundation/NSObject.h: Moved some headers to NSObjCRuntime.h
|
* Headers/Foundation/NSObject.h: Moved some headers to NSObjCRuntime.h
|
||||||
|
|
|
@ -55,6 +55,31 @@ NSString* const NSUndefinedKeyException = @"NSUnknownKeyException";
|
||||||
/* this should move into autoconf once it's accepted */
|
/* this should move into autoconf once it's accepted */
|
||||||
#define WANT_DEPRECATED_KVC_COMPAT 1
|
#define WANT_DEPRECATED_KVC_COMPAT 1
|
||||||
|
|
||||||
|
#ifdef WANT_DEPRECATED_KVC_COMPAT
|
||||||
|
|
||||||
|
static IMP takePath = 0;
|
||||||
|
static IMP takeValue = 0;
|
||||||
|
static IMP takePathKVO = 0;
|
||||||
|
static IMP takeValueKVO = 0;
|
||||||
|
|
||||||
|
static inline void setupCompat()
|
||||||
|
{
|
||||||
|
if (takePath == 0)
|
||||||
|
{
|
||||||
|
Class c = NSClassFromString(@"GSKVOBase");
|
||||||
|
|
||||||
|
takePathKVO = [c instanceMethodForSelector:
|
||||||
|
@selector(takeValue:forKeyPath:)];
|
||||||
|
takePath = [NSObject instanceMethodForSelector:
|
||||||
|
@selector(takeValue:forKeyPath:)];
|
||||||
|
takeValueKVO = [c instanceMethodForSelector:
|
||||||
|
@selector(takeValue:forKey:)];
|
||||||
|
takeValue = [NSObject instanceMethodForSelector:
|
||||||
|
@selector(takeValue:forKey:)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SetValueForKey(NSObject *self, id anObject, const char *key, unsigned size)
|
SetValueForKey(NSObject *self, id anObject, const char *key, unsigned size)
|
||||||
|
@ -340,16 +365,12 @@ static id ValueForKey(NSObject *self, const char *key, unsigned size)
|
||||||
unsigned size = [aKey length] * 8;
|
unsigned size = [aKey length] * 8;
|
||||||
char key[size+1];
|
char key[size+1];
|
||||||
#ifdef WANT_DEPRECATED_KVC_COMPAT
|
#ifdef WANT_DEPRECATED_KVC_COMPAT
|
||||||
static IMP o = 0;
|
IMP o = [self methodForSelector: @selector(takeValue:forKey:)];
|
||||||
|
|
||||||
/* Backward compatibility hack */
|
setupCompat();
|
||||||
if (o == 0)
|
if (o != takeValue && o != takeValueKVO)
|
||||||
{
|
{
|
||||||
o = [NSObject instanceMethodForSelector: @selector(takeValue:forKey:)];
|
(*o)(self, @selector(takeValue:forKey:), aKey);
|
||||||
}
|
|
||||||
if ([self methodForSelector: @selector(takeValue:forKey:)] != o)
|
|
||||||
{
|
|
||||||
[self takeValue: anObject forKey: aKey];
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -370,17 +391,12 @@ static id ValueForKey(NSObject *self, const char *key, unsigned size)
|
||||||
unsigned end = 0;
|
unsigned end = 0;
|
||||||
id obj = self;
|
id obj = self;
|
||||||
#ifdef WANT_DEPRECATED_KVC_COMPAT
|
#ifdef WANT_DEPRECATED_KVC_COMPAT
|
||||||
static IMP o = 0;
|
IMP o = [self methodForSelector: @selector(takeValue:forKeyPath:)];
|
||||||
|
|
||||||
/* Backward compatibility hack */
|
setupCompat();
|
||||||
if (o == 0)
|
if (o != takePath && o != takePathKVO)
|
||||||
{
|
{
|
||||||
o = [NSObject instanceMethodForSelector:
|
(*o)(self, @selector(takeValue:forKeyPath:), anObject, aKey);
|
||||||
@selector(takeValue:forKeyPath:)];
|
|
||||||
}
|
|
||||||
if ([self methodForSelector: @selector(takeValue:forKeyPath:)] != o)
|
|
||||||
{
|
|
||||||
[self takeValue: anObject forKeyPath: aKey];
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -143,12 +143,12 @@ static inline void setup()
|
||||||
NSMapTable *paths;
|
NSMapTable *paths;
|
||||||
NSMutableDictionary *changes;
|
NSMutableDictionary *changes;
|
||||||
}
|
}
|
||||||
- (void) notifyForKey: (NSString *)aKey ofChange: (NSDictionary *)change;
|
- (NSMutableDictionary *) changeForKey: (NSString *)key;
|
||||||
- (void) setChange: (NSDictionary *)info forKey: (NSString *)key;
|
- (void*) contextForObserver: (NSObject*)anObserver ofKeyPath: (NSString*)aPath;
|
||||||
- (NSDictionary *) changeForKey: (NSString *)key;
|
|
||||||
- (id) initWithInstance: (NSObject*)i;
|
- (id) initWithInstance: (NSObject*)i;
|
||||||
- (BOOL) isUnobserved;
|
- (BOOL) isUnobserved;
|
||||||
- (void*) contextForObserver: (NSObject*)anObserver ofKeyPath: (NSString*)aPath;
|
- (void) notifyForKey: (NSString *)aKey ofChange: (NSDictionary *)change;
|
||||||
|
- (void) setChange: (NSMutableDictionary *)info forKey: (NSString *)key;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -369,6 +369,22 @@ replacementForClass(Class c)
|
||||||
NSString *superName;
|
NSString *superName;
|
||||||
NSString *name;
|
NSString *name;
|
||||||
|
|
||||||
|
if ([aClass instanceMethodForSelector: @selector(takeValue:forKey:)]
|
||||||
|
!= [NSObject instanceMethodForSelector: @selector(takeValue:forKey:)])
|
||||||
|
{
|
||||||
|
NSLog(@"WARNING The class '%@' (or one of its superclasses) overrides"
|
||||||
|
@" the deprecated takeValue:forKey: method. Using KVO to observe"
|
||||||
|
@" this class may interfere with this method. Please change the"
|
||||||
|
@" class to override -setValue:forKey: instead.");
|
||||||
|
}
|
||||||
|
if ([aClass instanceMethodForSelector: @selector(takeValue:forKeyPath:)]
|
||||||
|
!= [NSObject instanceMethodForSelector: @selector(takeValue:forKeyPath:)])
|
||||||
|
{
|
||||||
|
NSLog(@"WARNING The class '%@' (or one of its superclasses) overrides"
|
||||||
|
@" the deprecated takeValue:forKeyPath: method. Using KVO to observe"
|
||||||
|
@" this class may interfere with this method. Please change the"
|
||||||
|
@" class to override -setValue:forKeyPath: instead.");
|
||||||
|
}
|
||||||
original = aClass;
|
original = aClass;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -797,6 +813,7 @@ replacementForClass(Class c)
|
||||||
{
|
{
|
||||||
if (paths != 0) NSFreeMapTable(paths);
|
if (paths != 0) NSFreeMapTable(paths);
|
||||||
RELEASE(iLock);
|
RELEASE(iLock);
|
||||||
|
RELEASE(changes);
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -846,13 +863,12 @@ replacementForClass(Class c)
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setChange: (NSDictionary *)info forKey: (NSString *)key
|
- (void) setChange: (NSMutableDictionary *)info forKey: (NSString *)key
|
||||||
{
|
{
|
||||||
[changes setValue: info forKey: key];
|
[changes setValue: info forKey: key];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary *) changeForKey: (NSString *)key
|
- (NSMutableDictionary *) changeForKey: (NSString *)key
|
||||||
{
|
{
|
||||||
return [changes valueForKey: key];
|
return [changes valueForKey: key];
|
||||||
}
|
}
|
||||||
|
@ -876,7 +892,7 @@ replacementForClass(Class c)
|
||||||
- (void) removeObserver: (NSObject*)anObserver forKeyPath: (NSString*)aPath
|
- (void) removeObserver: (NSObject*)anObserver forKeyPath: (NSString*)aPath
|
||||||
{
|
{
|
||||||
NSMapTable *observers;
|
NSMapTable *observers;
|
||||||
NSMapTable * observer;
|
NSMapTable *observer;
|
||||||
|
|
||||||
[iLock lock];
|
[iLock lock];
|
||||||
observers = (NSMapTable*)NSMapGet(paths, (void*)aPath);
|
observers = (NSMapTable*)NSMapGet(paths, (void*)aPath);
|
||||||
|
@ -899,8 +915,8 @@ replacementForClass(Class c)
|
||||||
- (void*) contextForObserver: (NSObject*)anObserver ofKeyPath: (NSString*)aPath
|
- (void*) contextForObserver: (NSObject*)anObserver ofKeyPath: (NSString*)aPath
|
||||||
{
|
{
|
||||||
NSMapTable *observers;
|
NSMapTable *observers;
|
||||||
NSMapTable * observer;
|
NSMapTable *observer;
|
||||||
void * context = 0;
|
void *context = 0;
|
||||||
|
|
||||||
[iLock lock];
|
[iLock lock];
|
||||||
observers = (NSMapTable*)NSMapGet(paths, (void*)aPath);
|
observers = (NSMapTable*)NSMapGet(paths, (void*)aPath);
|
||||||
|
@ -921,9 +937,9 @@ replacementForClass(Class c)
|
||||||
@implementation NSKeyValueObservationForwarder
|
@implementation NSKeyValueObservationForwarder
|
||||||
|
|
||||||
+ (id) forwarderWithKeyPath: (NSString *)keyPath
|
+ (id) forwarderWithKeyPath: (NSString *)keyPath
|
||||||
ofObject: (id)object
|
ofObject: (id)object
|
||||||
withTarget: (id)aTarget
|
withTarget: (id)aTarget
|
||||||
context: (void *)context
|
context: (void *)context
|
||||||
{
|
{
|
||||||
return [[self alloc] initWithKeyPath: keyPath
|
return [[self alloc] initWithKeyPath: keyPath
|
||||||
ofObject: object
|
ofObject: object
|
||||||
|
@ -1056,7 +1072,8 @@ replacementForClass(Class c)
|
||||||
{
|
{
|
||||||
id oldValue;
|
id oldValue;
|
||||||
|
|
||||||
oldValue = [observedObjectForForwarding valueForKey: keyForForwarding];
|
oldValue
|
||||||
|
= [observedObjectForForwarding valueForKey: keyForForwarding];
|
||||||
[observedObjectForForwarding removeObserver: self forKeyPath:
|
[observedObjectForForwarding removeObserver: self forKeyPath:
|
||||||
keyForForwarding];
|
keyForForwarding];
|
||||||
if (oldValue)
|
if (oldValue)
|
||||||
|
@ -1076,7 +1093,8 @@ replacementForClass(Class c)
|
||||||
| NSKeyValueObservingOptionOld
|
| NSKeyValueObservingOptionOld
|
||||||
context: target];
|
context: target];
|
||||||
//prepare change notification
|
//prepare change notification
|
||||||
newValue = [observedObjectForForwarding valueForKey: keyForForwarding];
|
newValue
|
||||||
|
= [observedObjectForForwarding valueForKey: keyForForwarding];
|
||||||
if (newValue)
|
if (newValue)
|
||||||
{
|
{
|
||||||
[change setObject: newValue forKey: NSKeyValueChangeNewKey];
|
[change setObject: newValue forKey: NSKeyValueChangeNewKey];
|
||||||
|
@ -1310,11 +1328,6 @@ replacementForClass(Class c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME
|
|
||||||
* It may be beneficial (performance-wise) to only calculate the old and new
|
|
||||||
* values in the willChange... and didChange... methods if explicitly needed
|
|
||||||
* by an observer.
|
|
||||||
*/
|
|
||||||
- (void) willChangeValueForKey: (NSString*)aKey
|
- (void) willChangeValueForKey: (NSString*)aKey
|
||||||
{
|
{
|
||||||
GSKVOInfo *info;
|
GSKVOInfo *info;
|
||||||
|
@ -1325,13 +1338,32 @@ replacementForClass(Class c)
|
||||||
id old;
|
id old;
|
||||||
NSMutableDictionary *change;
|
NSMutableDictionary *change;
|
||||||
|
|
||||||
change = [NSMutableDictionary dictionary];
|
change = [info changeForKey: aKey];
|
||||||
old = [self valueForKey: aKey];
|
if (change == nil)
|
||||||
if (old != nil)
|
{
|
||||||
|
change = [[NSMutableDictionary alloc] initWithCapacity: 1];
|
||||||
|
[info setChange: change forKey: aKey];
|
||||||
|
RELEASE(change);
|
||||||
|
}
|
||||||
|
old = [change objectForKey: NSKeyValueChangeNewKey];
|
||||||
|
if (old == nil)
|
||||||
|
{
|
||||||
|
old = [self valueForKey: aKey];
|
||||||
|
if (old == nil)
|
||||||
|
{
|
||||||
|
[change removeObjectForKey: NSKeyValueChangeOldKey];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[change setObject: old forKey: NSKeyValueChangeOldKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
[change setObject: old forKey: NSKeyValueChangeOldKey];
|
[change setObject: old forKey: NSKeyValueChangeOldKey];
|
||||||
}
|
}
|
||||||
[info setChange: change forKey: aKey];
|
[change removeObjectForKey: NSKeyValueChangeNewKey];
|
||||||
|
[change removeObjectForKey: NSKeyValueChangeKindKey];
|
||||||
}
|
}
|
||||||
[self willChangeValueForDependentsOfKey: aKey];
|
[self willChangeValueForDependentsOfKey: aKey];
|
||||||
}
|
}
|
||||||
|
@ -1350,9 +1382,7 @@ replacementForClass(Class c)
|
||||||
forKey: NSKeyValueChangeNewKey];
|
forKey: NSKeyValueChangeNewKey];
|
||||||
[change setValue: [NSNumber numberWithInt: NSKeyValueChangeSetting]
|
[change setValue: [NSNumber numberWithInt: NSKeyValueChangeSetting]
|
||||||
forKey: NSKeyValueChangeKindKey];
|
forKey: NSKeyValueChangeKindKey];
|
||||||
|
|
||||||
[info notifyForKey: aKey ofChange: change];
|
[info notifyForKey: aKey ofChange: change];
|
||||||
[info setChange: nil forKey: aKey];
|
|
||||||
}
|
}
|
||||||
[self didChangeValueForDependentsOfKey: aKey];
|
[self didChangeValueForDependentsOfKey: aKey];
|
||||||
}
|
}
|
||||||
|
@ -1384,7 +1414,6 @@ replacementForClass(Class c)
|
||||||
}
|
}
|
||||||
|
|
||||||
[info notifyForKey: aKey ofChange: change];
|
[info notifyForKey: aKey ofChange: change];
|
||||||
[info setChange:nil forKey: aKey];
|
|
||||||
}
|
}
|
||||||
[self didChangeValueForDependentsOfKey: aKey];
|
[self didChangeValueForDependentsOfKey: aKey];
|
||||||
}
|
}
|
||||||
|
@ -1397,10 +1426,10 @@ replacementForClass(Class c)
|
||||||
|
|
||||||
info = [self observationInfo];
|
info = [self observationInfo];
|
||||||
{
|
{
|
||||||
NSDictionary *change;
|
NSMutableDictionary *change;
|
||||||
NSMutableArray *array;
|
NSMutableArray *array;
|
||||||
|
|
||||||
change = [NSMutableDictionary dictionary];
|
change = [[NSMutableDictionary alloc] initWithCapacity: 1];
|
||||||
array = [self valueForKey: aKey];
|
array = [self valueForKey: aKey];
|
||||||
|
|
||||||
if (changeKind == NSKeyValueChangeRemoval
|
if (changeKind == NSKeyValueChangeRemoval
|
||||||
|
@ -1411,6 +1440,7 @@ replacementForClass(Class c)
|
||||||
}
|
}
|
||||||
|
|
||||||
[info setChange: change forKey: aKey];
|
[info setChange: change forKey: aKey];
|
||||||
|
RELEASE(change);
|
||||||
}
|
}
|
||||||
[self willChangeValueForDependentsOfKey: aKey];
|
[self willChangeValueForDependentsOfKey: aKey];
|
||||||
}
|
}
|
||||||
|
@ -1424,14 +1454,15 @@ replacementForClass(Class c)
|
||||||
info = [self observationInfo];
|
info = [self observationInfo];
|
||||||
if (info != nil)
|
if (info != nil)
|
||||||
{
|
{
|
||||||
NSDictionary *change;
|
NSMutableDictionary *change;
|
||||||
NSMutableSet *set;
|
NSMutableSet *set;
|
||||||
|
|
||||||
change = [NSMutableDictionary dictionary];
|
change = [[NSMutableDictionary alloc] initWithCapacity: 1];
|
||||||
set = [self valueForKey: aKey];
|
set = [self valueForKey: aKey];
|
||||||
|
|
||||||
[change setValue: [set mutableCopy] forKey: @"oldSet"];
|
[change setValue: [set mutableCopy] forKey: @"oldSet"];
|
||||||
[info setChange: change forKey: aKey];
|
[info setChange: change forKey: aKey];
|
||||||
|
RELEASE(change);
|
||||||
}
|
}
|
||||||
[self willChangeValueForDependentsOfKey: aKey];
|
[self willChangeValueForDependentsOfKey: aKey];
|
||||||
}
|
}
|
||||||
|
@ -1485,7 +1516,6 @@ replacementForClass(Class c)
|
||||||
[change setValue: new forKey: NSKeyValueChangeNewKey];
|
[change setValue: new forKey: NSKeyValueChangeNewKey];
|
||||||
}
|
}
|
||||||
[info notifyForKey: aKey ofChange: change];
|
[info notifyForKey: aKey ofChange: change];
|
||||||
[info setChange:nil forKey: aKey];
|
|
||||||
}
|
}
|
||||||
[self didChangeValueForDependentsOfKey: aKey];
|
[self didChangeValueForDependentsOfKey: aKey];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue