mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-21 04:32:03 +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>
|
||||
|
||||
* 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 */
|
||||
#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
|
||||
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;
|
||||
char key[size+1];
|
||||
#ifdef WANT_DEPRECATED_KVC_COMPAT
|
||||
static IMP o = 0;
|
||||
IMP o = [self methodForSelector: @selector(takeValue:forKey:)];
|
||||
|
||||
/* Backward compatibility hack */
|
||||
if (o == 0)
|
||||
setupCompat();
|
||||
if (o != takeValue && o != takeValueKVO)
|
||||
{
|
||||
o = [NSObject instanceMethodForSelector: @selector(takeValue:forKey:)];
|
||||
}
|
||||
if ([self methodForSelector: @selector(takeValue:forKey:)] != o)
|
||||
{
|
||||
[self takeValue: anObject forKey: aKey];
|
||||
(*o)(self, @selector(takeValue:forKey:), aKey);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -370,17 +391,12 @@ static id ValueForKey(NSObject *self, const char *key, unsigned size)
|
|||
unsigned end = 0;
|
||||
id obj = self;
|
||||
#ifdef WANT_DEPRECATED_KVC_COMPAT
|
||||
static IMP o = 0;
|
||||
IMP o = [self methodForSelector: @selector(takeValue:forKeyPath:)];
|
||||
|
||||
/* Backward compatibility hack */
|
||||
if (o == 0)
|
||||
setupCompat();
|
||||
if (o != takePath && o != takePathKVO)
|
||||
{
|
||||
o = [NSObject instanceMethodForSelector:
|
||||
@selector(takeValue:forKeyPath:)];
|
||||
}
|
||||
if ([self methodForSelector: @selector(takeValue:forKeyPath:)] != o)
|
||||
{
|
||||
[self takeValue: anObject forKeyPath: aKey];
|
||||
(*o)(self, @selector(takeValue:forKeyPath:), anObject, aKey);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -143,12 +143,12 @@ static inline void setup()
|
|||
NSMapTable *paths;
|
||||
NSMutableDictionary *changes;
|
||||
}
|
||||
- (void) notifyForKey: (NSString *)aKey ofChange: (NSDictionary *)change;
|
||||
- (void) setChange: (NSDictionary *)info forKey: (NSString *)key;
|
||||
- (NSDictionary *) changeForKey: (NSString *)key;
|
||||
- (NSMutableDictionary *) changeForKey: (NSString *)key;
|
||||
- (void*) contextForObserver: (NSObject*)anObserver ofKeyPath: (NSString*)aPath;
|
||||
- (id) initWithInstance: (NSObject*)i;
|
||||
- (BOOL) isUnobserved;
|
||||
- (void*) contextForObserver: (NSObject*)anObserver ofKeyPath: (NSString*)aPath;
|
||||
- (void) notifyForKey: (NSString *)aKey ofChange: (NSDictionary *)change;
|
||||
- (void) setChange: (NSMutableDictionary *)info forKey: (NSString *)key;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -369,6 +369,22 @@ replacementForClass(Class c)
|
|||
NSString *superName;
|
||||
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;
|
||||
|
||||
/*
|
||||
|
@ -797,6 +813,7 @@ replacementForClass(Class c)
|
|||
{
|
||||
if (paths != 0) NSFreeMapTable(paths);
|
||||
RELEASE(iLock);
|
||||
RELEASE(changes);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
@ -846,13 +863,12 @@ replacementForClass(Class c)
|
|||
return self;
|
||||
}
|
||||
|
||||
- (void) setChange: (NSDictionary *)info forKey: (NSString *)key
|
||||
- (void) setChange: (NSMutableDictionary *)info forKey: (NSString *)key
|
||||
{
|
||||
[changes setValue: info forKey: key];
|
||||
|
||||
}
|
||||
|
||||
- (NSDictionary *) changeForKey: (NSString *)key
|
||||
- (NSMutableDictionary *) changeForKey: (NSString *)key
|
||||
{
|
||||
return [changes valueForKey: key];
|
||||
}
|
||||
|
@ -1056,7 +1072,8 @@ replacementForClass(Class c)
|
|||
{
|
||||
id oldValue;
|
||||
|
||||
oldValue = [observedObjectForForwarding valueForKey: keyForForwarding];
|
||||
oldValue
|
||||
= [observedObjectForForwarding valueForKey: keyForForwarding];
|
||||
[observedObjectForForwarding removeObserver: self forKeyPath:
|
||||
keyForForwarding];
|
||||
if (oldValue)
|
||||
|
@ -1076,7 +1093,8 @@ replacementForClass(Class c)
|
|||
| NSKeyValueObservingOptionOld
|
||||
context: target];
|
||||
//prepare change notification
|
||||
newValue = [observedObjectForForwarding valueForKey: keyForForwarding];
|
||||
newValue
|
||||
= [observedObjectForForwarding valueForKey: keyForForwarding];
|
||||
if (newValue)
|
||||
{
|
||||
[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
|
||||
{
|
||||
GSKVOInfo *info;
|
||||
|
@ -1325,13 +1338,32 @@ replacementForClass(Class c)
|
|||
id old;
|
||||
NSMutableDictionary *change;
|
||||
|
||||
change = [NSMutableDictionary dictionary];
|
||||
change = [info changeForKey: aKey];
|
||||
if (change == 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)
|
||||
if (old == nil)
|
||||
{
|
||||
[change removeObjectForKey: NSKeyValueChangeOldKey];
|
||||
}
|
||||
else
|
||||
{
|
||||
[change setObject: old forKey: NSKeyValueChangeOldKey];
|
||||
}
|
||||
[info setChange: change forKey: aKey];
|
||||
}
|
||||
else
|
||||
{
|
||||
[change setObject: old forKey: NSKeyValueChangeOldKey];
|
||||
}
|
||||
[change removeObjectForKey: NSKeyValueChangeNewKey];
|
||||
[change removeObjectForKey: NSKeyValueChangeKindKey];
|
||||
}
|
||||
[self willChangeValueForDependentsOfKey: aKey];
|
||||
}
|
||||
|
@ -1350,9 +1382,7 @@ replacementForClass(Class c)
|
|||
forKey: NSKeyValueChangeNewKey];
|
||||
[change setValue: [NSNumber numberWithInt: NSKeyValueChangeSetting]
|
||||
forKey: NSKeyValueChangeKindKey];
|
||||
|
||||
[info notifyForKey: aKey ofChange: change];
|
||||
[info setChange: nil forKey: aKey];
|
||||
}
|
||||
[self didChangeValueForDependentsOfKey: aKey];
|
||||
}
|
||||
|
@ -1384,7 +1414,6 @@ replacementForClass(Class c)
|
|||
}
|
||||
|
||||
[info notifyForKey: aKey ofChange: change];
|
||||
[info setChange:nil forKey: aKey];
|
||||
}
|
||||
[self didChangeValueForDependentsOfKey: aKey];
|
||||
}
|
||||
|
@ -1397,10 +1426,10 @@ replacementForClass(Class c)
|
|||
|
||||
info = [self observationInfo];
|
||||
{
|
||||
NSDictionary *change;
|
||||
NSMutableDictionary *change;
|
||||
NSMutableArray *array;
|
||||
|
||||
change = [NSMutableDictionary dictionary];
|
||||
change = [[NSMutableDictionary alloc] initWithCapacity: 1];
|
||||
array = [self valueForKey: aKey];
|
||||
|
||||
if (changeKind == NSKeyValueChangeRemoval
|
||||
|
@ -1411,6 +1440,7 @@ replacementForClass(Class c)
|
|||
}
|
||||
|
||||
[info setChange: change forKey: aKey];
|
||||
RELEASE(change);
|
||||
}
|
||||
[self willChangeValueForDependentsOfKey: aKey];
|
||||
}
|
||||
|
@ -1424,14 +1454,15 @@ replacementForClass(Class c)
|
|||
info = [self observationInfo];
|
||||
if (info != nil)
|
||||
{
|
||||
NSDictionary *change;
|
||||
NSMutableDictionary *change;
|
||||
NSMutableSet *set;
|
||||
|
||||
change = [NSMutableDictionary dictionary];
|
||||
change = [[NSMutableDictionary alloc] initWithCapacity: 1];
|
||||
set = [self valueForKey: aKey];
|
||||
|
||||
[change setValue: [set mutableCopy] forKey: @"oldSet"];
|
||||
[info setChange: change forKey: aKey];
|
||||
RELEASE(change);
|
||||
}
|
||||
[self willChangeValueForDependentsOfKey: aKey];
|
||||
}
|
||||
|
@ -1485,7 +1516,6 @@ replacementForClass(Class c)
|
|||
[change setValue: new forKey: NSKeyValueChangeNewKey];
|
||||
}
|
||||
[info notifyForKey: aKey ofChange: change];
|
||||
[info setChange:nil forKey: aKey];
|
||||
}
|
||||
[self didChangeValueForDependentsOfKey: aKey];
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue