mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 09:04:13 +00:00
KVC updates
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20828 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
c5b59c788c
commit
826de16ee7
6 changed files with 453 additions and 88 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
2005-03-02 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Headers/Foundation/NSKeyValueCoding.h:
|
||||
* Source/NSArray.m:
|
||||
* Source/NSKeyValueCoding.m:
|
||||
* Source/Additions/GSObjCRuntime.m:
|
||||
On the way back from FOSDEM I updated tje key-value-coding stuff to
|
||||
match the lastest version from Apple/MacOS-X panther.
|
||||
I don't use KVC in my code, and have not testcases for it, so would
|
||||
appreciate it if anyone who does could try this out and get bug
|
||||
reports back to me ASAP.
|
||||
|
||||
2005-03-01 Adam Fedor <fedor@gnu.org>
|
||||
|
||||
* Source/NSBundle.m (+gnustepBundle,
|
||||
|
|
|
@ -28,7 +28,9 @@
|
|||
#include <Foundation/NSObject.h>
|
||||
|
||||
@class NSArray;
|
||||
@class NSMutableArray;
|
||||
@class NSDictionary;
|
||||
@class NSError;
|
||||
@class NSString;
|
||||
|
||||
#ifndef STRICT_OPENSTEP
|
||||
|
@ -66,24 +68,92 @@ GS_EXPORT NSString* const NSUnknownKeyException;
|
|||
+ (BOOL) useStoredAccessor;
|
||||
|
||||
/**
|
||||
* Invoked when -valueForKey: / -storedValueForKey: are called with a key,
|
||||
* which can't be associated with an accessor method or instance variable.
|
||||
* Subclasses may override this method to add custom handling. NSObject
|
||||
* raises an NSUnknownKeyException, with a userInfo dictionary containing
|
||||
* NSTargetObjectUserInfoKey with the receiver an NSUnknownUserInfoKey with
|
||||
* the supplied key entries.
|
||||
* Returns a dictionary built from values obtained for the specified keys.<br />
|
||||
* By default this is derived by calling -valueForKey: for each key.
|
||||
* Any nil values obtained are represented by an [NSNull] instance.
|
||||
*/
|
||||
- (NSDictionary*) dictionaryWithValuesForKeys: (NSArray*)keys;
|
||||
|
||||
/**
|
||||
* Deprecated ... use -valueForUndefinedKey: instead.
|
||||
*/
|
||||
- (id) handleQueryWithUnboundKey: (NSString*)aKey;
|
||||
|
||||
/**
|
||||
* Invoked when -takeValue:forKey: / -takeStoredValue:forKey: are called with
|
||||
* Deprecated, use -setValue:forUndefinedKey: instead.
|
||||
*/
|
||||
- (void) handleTakeValue: (id)anObject forUnboundKey: (NSString*)aKey;
|
||||
|
||||
/**
|
||||
* <strong>Not implemented</strong> ... I don't know what this method
|
||||
* is good for ... do we need to copy MacOS-X and implement it?
|
||||
*/
|
||||
- (NSMutableArray*) mutableArrayValueForKey: (NSString*)aKey;
|
||||
|
||||
/**
|
||||
* <strong>Not implemented</strong> ... I don't know what this method
|
||||
* is good for ... do we need to copy MacOS-X and implement it?
|
||||
*/
|
||||
- (NSMutableArray*) mutableArrayValueForKeyPath: (NSString*)aKey;
|
||||
|
||||
/**
|
||||
* This method is invoked by the NSKeyValueCoding mechanism when an attempt
|
||||
* is made to set an null value for a scalar attribute. This implementation
|
||||
* raises an NSInvalidArgument exception. Subclasses my override this method
|
||||
* to do custom handling. (E.g. setting the value to the equivalent of 0.)
|
||||
*/
|
||||
- (void) setNilValueForKey: (NSString*)aKey;
|
||||
|
||||
/**
|
||||
* Sets the value if the attribute associated with the key in the receiver.
|
||||
* The object is converted to a scalar attribute where applicable (and
|
||||
* -setNilValueForKey: is caalled if a nil value is supplied).
|
||||
* Tries to use a standard accessor of the form setKey: where 'Key' is the
|
||||
* supplied argument with the first letter convertyed to uppercase.<br />
|
||||
* If the receiver's class allows +accessInstanceVariablesDirectly
|
||||
* it continues with instance variables:
|
||||
* <list>
|
||||
* <item>_key</item>
|
||||
* <item>_isKey</item>
|
||||
* <item>key</item>
|
||||
* <item>isKey</item>
|
||||
* </list>
|
||||
* Invokes -setValue:forUndefinedKey: if no accessor mechanism can be found
|
||||
* and raises NSInvalidArgumentException if the accesor method doesn't take
|
||||
* exactly one argument or the type is unsupported (e.g. structs).
|
||||
* If the receiver expects a scalar value and the value supplied
|
||||
* is the NSNull instance or nil, this method invokes
|
||||
* -setNilValueForKey: .
|
||||
*/
|
||||
- (void) setValue: (id)anObject forKey: (NSString*)aKey;
|
||||
|
||||
/**
|
||||
* Retrieves the object returned by invoking -valueForKey:
|
||||
* on the receiver with the first key component supplied by the key path.
|
||||
* Then invokes -setValue:forKeyPath: recursively on the
|
||||
* returned object with rest of the key path.
|
||||
* The key components are delimated by '.'.
|
||||
* If the key path doesn't contain any '.', this method simply
|
||||
* invokes -setValue:forKey:.
|
||||
*/
|
||||
- (void) setValue: (id)anObject forKeyPath: (NSString*)aKey;
|
||||
|
||||
/**
|
||||
* Invoked when -setValue:forKey: / -takeStoredValue:forKey: are called with
|
||||
* a key which can't be associated with an accessor method or instance
|
||||
* variable. Subclasses may override this method to add custom handling.
|
||||
* NSObject raises an NSUnknownKeyException, with a userInfo dictionary
|
||||
* containing NSTargetObjectUserInfoKey with the receiver an
|
||||
* NSUnknownUserInfoKey with the supplied key entries.
|
||||
* NSUnknownUserInfoKey with the supplied key entries.<br />
|
||||
* Called when the key passed to -setValue:forKey: cannot be used.
|
||||
*/
|
||||
- (void) handleTakeValue: (id)anObject forUnboundKey: (NSString*)aKey;
|
||||
- (void) setValue: (id)anObject forUndefinedKey: (NSString*)aKey;
|
||||
|
||||
/**
|
||||
* Uses -setValue:forKey: to place the values from aDictionary in the
|
||||
* receiver.
|
||||
*/
|
||||
- (void) setValuesForKeysWithDictionary: (NSDictionary*)aDictionary;
|
||||
|
||||
/**
|
||||
* Returns the value associated with the supplied key as an object.
|
||||
|
@ -108,7 +178,7 @@ GS_EXPORT NSString* const NSUnknownKeyException;
|
|||
* <item>getKey</item>
|
||||
* <item>key</item>
|
||||
* </list>
|
||||
* Invokes -handleQueryWithUnboundKey: if no accessor mechanism can be
|
||||
* Invokes -handleTakeValue:forUnboundKey: if no accessor mechanism can be
|
||||
* found and raises NSInvalidArgumentException if the accesor method takes
|
||||
* takes any arguments or the type is unsupported (e.g. structs).
|
||||
*/
|
||||
|
@ -173,7 +243,8 @@ GS_EXPORT NSString* const NSUnknownKeyException;
|
|||
* exactly one argument or the type is unsupported (e.g. structs).
|
||||
* If the receiver expects a scalar value and the value supplied
|
||||
* is the NSNull instance or nil, this method invokes
|
||||
* -unableToSetNilForKey: .
|
||||
* -unableToSetNilForKey: .<br />
|
||||
* Deprecated ... use -setValue:forKey: instead.
|
||||
*/
|
||||
- (void) takeValue: (id)anObject forKey: (NSString*)aKey;
|
||||
|
||||
|
@ -184,44 +255,67 @@ GS_EXPORT NSString* const NSUnknownKeyException;
|
|||
* returned object with rest of the key path.
|
||||
* The key components are delimated by '.'.
|
||||
* If the key path doesn't contain any '.', this method simply
|
||||
* invokes -takeValue:forKey:.
|
||||
* invokes -takeValue:forKey:.<br />
|
||||
* Deprecated ... use -setValue:forKeyPath: instead.
|
||||
*/
|
||||
- (void) takeValue: (id)anObject forKeyPath: (NSString*)aKey;
|
||||
|
||||
/**
|
||||
* Iterates over the dictionary invoking -takeValue:forKey:
|
||||
* on the receiver for each key-value pair, converting NSNull to nil.
|
||||
* on the receiver for each key-value pair, converting NSNull to nil.<br />
|
||||
* Deprecated ... use -setValuesForKeysWithDictionary: instead.
|
||||
*/
|
||||
- (void) takeValuesFromDictionary: (NSDictionary*)aDictionary;
|
||||
|
||||
/**
|
||||
* This method is invoked by the NSKeyValueCoding mechanism when an attempt
|
||||
* is made to set an null value for a scalar attribute. This implementation
|
||||
* raises an NSInvalidArgument exception. Subclasses my override this method
|
||||
* to do custom handling. (E.g. setting the value to the equivalent of 0.)
|
||||
* Deprecated ... use -setNilValueForKey: instead.
|
||||
*/
|
||||
- (void) unableToSetNilForKey: (NSString*)aKey;
|
||||
|
||||
|
||||
/**
|
||||
* Returns a boolean indicating whether the object pointed to by aValue
|
||||
* is valid for settting as an attribute of the receiver using the name
|
||||
* aKey. On success (YES response) it may return a new value to be used
|
||||
* in aValue. On failure (NO response) it may return an error in anError.<br />
|
||||
* The method works by calling a method of the receiver whose name is of
|
||||
* the form validateKey:error: if the receiver has implemented such a
|
||||
* method, otherwise it simply returns YES.
|
||||
*/
|
||||
- (BOOL) validateValue: (id*)aValue
|
||||
forKey: (NSString*)aKey
|
||||
error: (NSError**)anError;
|
||||
|
||||
/**
|
||||
* Returns the result of calling -validateValue:forKey:error: on the receiver
|
||||
* using aPath to determine the key value in the same manner as the
|
||||
* -valueForKeyPath: method.
|
||||
*/
|
||||
- (BOOL) validateValue: (id*)aValue
|
||||
forKeyPath: (NSString*)aKey
|
||||
error: (NSError**)anError;
|
||||
|
||||
/**
|
||||
* Returns the value associated with the supplied key as an object.
|
||||
* Scalar attributes are converted to corresponding objects.
|
||||
* The value-NSKeyValueCoding use the public accessors
|
||||
* in favor of the private ones.
|
||||
* Scalar attributes are converted to corresponding objects.<br />
|
||||
* The search order is:<br/>
|
||||
* Accessor methods:
|
||||
* <list>
|
||||
* <item>getKey</item>
|
||||
* <item>key</item>
|
||||
* </list>
|
||||
* If the receiver's class allows +accessInstanceVariablesDirectly
|
||||
* it continues with private accessors:
|
||||
* <list>
|
||||
* <item>_getKey</item>
|
||||
* <item>_key</item>
|
||||
* </list>
|
||||
* If the receiver's class allows +accessInstanceVariablesDirectly
|
||||
* it continues with instance variables:
|
||||
* and then instance variables:
|
||||
* <list>
|
||||
* <item>key</item>
|
||||
* <item>_key</item>
|
||||
* </list>
|
||||
* Invokes -handleQueryWithUnboundKey:
|
||||
* Invokes -setValue:forUndefinedKey:
|
||||
* if no accessor mechanism can be found
|
||||
* and raises NSInvalidArgumentException if the accesor method takes
|
||||
* any arguments or the type is unsupported (e.g. structs).
|
||||
|
@ -238,6 +332,16 @@ GS_EXPORT NSString* const NSUnknownKeyException;
|
|||
*/
|
||||
- (id) valueForKeyPath: (NSString*)aKey;
|
||||
|
||||
/**
|
||||
* Invoked when -valueForKey: / -storedValueForKey: are called with a key,
|
||||
* which can't be associated with an accessor method or instance variable.
|
||||
* Subclasses may override this method to add custom handling. NSObject
|
||||
* raises an NSUnknownKeyException, with a userInfo dictionary containing
|
||||
* NSTargetObjectUserInfoKey with the receiver an NSUnknownUserInfoKey with
|
||||
* the supplied key entries.<br />
|
||||
*/
|
||||
- (id) valueForUndefinedKey: (NSString*)aKey;
|
||||
|
||||
/**
|
||||
* Iterates over the array sending the receiver -valueForKey:
|
||||
* for each object in the array and inserting the result in a dictionary.
|
||||
|
|
|
@ -1511,7 +1511,7 @@ GSObjCGetValue(NSObject *self, NSString *key, SEL sel,
|
|||
}
|
||||
if (type == NULL)
|
||||
{
|
||||
return [self handleQueryWithUnboundKey: key];
|
||||
return [self valueForUndefinedKey: key];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1834,11 +1834,11 @@ GSObjCSetValue(NSObject *self, NSString *key, id val, SEL sel,
|
|||
}
|
||||
if (type == NULL)
|
||||
{
|
||||
[self handleTakeValue: val forUnboundKey: key];
|
||||
[self setValue: val forUndefinedKey: key];
|
||||
}
|
||||
else if ((val == nil || val == null) && *type != _C_ID && *type != _C_CLASS)
|
||||
{
|
||||
[self unableToSetNilForKey: key];
|
||||
[self setNilValueForKey: key];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1251,7 +1251,7 @@ compare(id elem1, id elem2, void* context)
|
|||
unsigned count = [self count];
|
||||
volatile id object = nil;
|
||||
|
||||
results = [NSMutableArray array];
|
||||
results = [NSMutableArray arrayWithCapacity: count];
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
|
|
|
@ -595,8 +595,8 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
|
|||
path. (Using '/' here is safe; it isn't the path separator
|
||||
everywhere, but it is on all systems that have PROCFS_EXE_LINK.)
|
||||
*/
|
||||
if ([_executable_path length] > 0 &&
|
||||
[_executable_path characterAtIndex: 0] != '/')
|
||||
if ([_executable_path length] > 0
|
||||
&& [_executable_path characterAtIndex: 0] != '/')
|
||||
{
|
||||
_executable_path = nil;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,27 @@ NSString* const NSUnknownKeyException = @"NSUnknownKeyException";
|
|||
}
|
||||
|
||||
|
||||
- (NSDictionary*) dictionaryWithValuesForKeys: (NSArray*)keys
|
||||
{
|
||||
NSMutableDictionary *dictionary;
|
||||
NSEnumerator *enumerator;
|
||||
id key;
|
||||
|
||||
dictionary = [NSMutableDictionary dictionaryWithCapacity: [keys count]];
|
||||
enumerator = [keys objectEnumerator];
|
||||
while ((key = [enumerator nextObject]) != nil)
|
||||
{
|
||||
id value = [self valueForKey: key];
|
||||
|
||||
if (value == nil)
|
||||
{
|
||||
value = [NSNull null];
|
||||
}
|
||||
[dictionary setObject: value forKey: key];
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
- (id) handleQueryWithUnboundKey: (NSString*)aKey
|
||||
{
|
||||
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
|
@ -64,6 +85,8 @@ NSString* const NSUnknownKeyException = @"NSUnknownKeyException";
|
|||
NSException *exp = [NSException exceptionWithName: NSUnknownKeyException
|
||||
reason: @"Unable to find value for key"
|
||||
userInfo: dict];
|
||||
|
||||
GSOnceMLog(@"This method is deprecated, use -valueForUndefinedKey:");
|
||||
[exp raise];
|
||||
return nil;
|
||||
}
|
||||
|
@ -80,10 +103,168 @@ NSString* const NSUnknownKeyException = @"NSUnknownKeyException";
|
|||
NSException *exp = [NSException exceptionWithName: NSUnknownKeyException
|
||||
reason: @"Unable to set value for key"
|
||||
userInfo: dict];
|
||||
GSOnceMLog(@"This method is deprecated, use -setValue:forUndefinedKey:");
|
||||
[exp raise];
|
||||
}
|
||||
|
||||
|
||||
- (NSMutableArray*) mutableArrayValueForKey: (NSString*)aKey
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSMutableArray*) mutableArrayValueForKeyPath: (NSString*)aKey
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void) setNilValueForKey: (NSString*)aKey
|
||||
{
|
||||
/* Backward compatibility hack */
|
||||
if ([self methodForSelector: @selector(unableToSetNilForKey:)]
|
||||
== [NSObject instanceMethodForSelector: @selector(unableToSetNilForKey:)])
|
||||
{
|
||||
[self unableToSetNilForKey: aKey];
|
||||
}
|
||||
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"%@ -- %@ 0x%x: Given nil value to set for key \"%@\"",
|
||||
NSStringFromSelector(_cmd), NSStringFromClass([self class]), self, aKey];
|
||||
}
|
||||
|
||||
|
||||
- (void) setValue: (id)anObject forKey: (NSString*)aKey
|
||||
{
|
||||
SEL sel = 0;
|
||||
const char *type = 0;
|
||||
int off;
|
||||
unsigned size = [aKey length];
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
const char *name;
|
||||
char buf[size+6];
|
||||
char lo;
|
||||
char hi;
|
||||
|
||||
strcpy(buf, "_set");
|
||||
[aKey getCString: &buf[4]];
|
||||
lo = buf[4];
|
||||
hi = islower(lo) ? toupper(lo) : lo;
|
||||
buf[4] = hi;
|
||||
buf[size+4] = ':';
|
||||
buf[size+5] = '\0';
|
||||
|
||||
name = &buf[1]; // setKey:
|
||||
type = NULL;
|
||||
sel = GSSelectorFromName(name);
|
||||
if (sel == 0 || [self respondsToSelector: sel] == NO)
|
||||
{
|
||||
name = buf; // _setKey:
|
||||
sel = GSSelectorFromName(name);
|
||||
if (sel == 0 || [self respondsToSelector: sel] == NO)
|
||||
{
|
||||
sel = 0;
|
||||
if ([[self class] accessInstanceVariablesDirectly] == YES)
|
||||
{
|
||||
buf[size+4] = '\0';
|
||||
buf[3] = '_';
|
||||
buf[4] = lo;
|
||||
name = &buf[3]; // _key
|
||||
if (GSObjCFindVariable(self, name, &type, &size, &off) == NO)
|
||||
{
|
||||
buf[4] = hi;
|
||||
buf[3] = 's';
|
||||
buf[2] = 'i';
|
||||
buf[1] = '_';
|
||||
name = &buf[1]; // _isKey
|
||||
if (GSObjCFindVariable(self,
|
||||
name, &type, &size, &off) == NO)
|
||||
{
|
||||
buf[4] = lo;
|
||||
name = &buf[4]; // key
|
||||
if (GSObjCFindVariable(self,
|
||||
name, &type, &size, &off) == NO)
|
||||
{
|
||||
buf[4] = hi;
|
||||
buf[3] = 's';
|
||||
buf[2] = 'i';
|
||||
name = &buf[2]; // isKey
|
||||
GSObjCFindVariable(self,
|
||||
name, &type, &size, &off);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GSOnceMLog(@"Key-value access using _setKey: isdeprecated:");
|
||||
}
|
||||
}
|
||||
}
|
||||
GSObjCSetValue(self, aKey, anObject, sel, type, size, off);
|
||||
}
|
||||
|
||||
|
||||
- (void) setValue: (id)anObject forKeyPath: (NSString*)aKey
|
||||
{
|
||||
NSRange r = [aKey rangeOfString: @"."];
|
||||
|
||||
if (r.length == 0)
|
||||
{
|
||||
[self setValue: anObject forKey: aKey];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString *key = [aKey substringToIndex: r.location];
|
||||
NSString *path = [aKey substringFromIndex: NSMaxRange(r)];
|
||||
|
||||
[[self valueForKey: key] setValue: anObject forKeyPath: path];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) setValue: (id)anObject forUndefinedKey: (NSString*)aKey
|
||||
{
|
||||
NSDictionary *dict;
|
||||
NSException *exp;
|
||||
|
||||
/* Backward compatibility hack */
|
||||
if ([self methodForSelector: @selector(handleTakeValue:forUnboundKey:)]
|
||||
== [NSObject instanceMethodForSelector:
|
||||
@selector(handleTakeValue:forUnboundKey:)])
|
||||
{
|
||||
[self handleTakeValue: anObject forUnboundKey: aKey];
|
||||
}
|
||||
|
||||
dict = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
(anObject ? anObject : @"(nil)"),
|
||||
@"NSTargetObjectUserInfoKey",
|
||||
(aKey ? aKey : @"(nil)"),
|
||||
@"NSUnknownUserInfoKey",
|
||||
nil];
|
||||
exp = [NSException exceptionWithName: NSInvalidArgumentException
|
||||
reason: @"Unable to set nil value for key"
|
||||
userInfo: dict];
|
||||
[exp raise];
|
||||
}
|
||||
|
||||
|
||||
- (void) setValuesForKeysWithDictionary: (NSDictionary*)aDictionary
|
||||
{
|
||||
NSEnumerator *enumerator = [aDictionary keyEnumerator];
|
||||
NSString *key;
|
||||
|
||||
while ((key = [enumerator nextObject]) != nil)
|
||||
{
|
||||
[self setValue: [aDictionary objectForKey: key] forKey: key];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (id) storedValueForKey: (NSString*)aKey
|
||||
{
|
||||
unsigned size;
|
||||
|
@ -94,17 +275,11 @@ NSString* const NSUnknownKeyException = @"NSUnknownKeyException";
|
|||
}
|
||||
|
||||
size = [aKey cStringLength];
|
||||
if (size < 1)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"storedValueForKey: ... empty key"];
|
||||
return NO; // avoid compiler warnings.
|
||||
}
|
||||
else
|
||||
if (size > 0)
|
||||
{
|
||||
SEL sel = 0;
|
||||
const char *type = NULL;
|
||||
unsigned off;
|
||||
int off;
|
||||
const char *name;
|
||||
char buf[size+5];
|
||||
char lo;
|
||||
|
@ -158,8 +333,13 @@ NSString* const NSUnknownKeyException = @"NSUnknownKeyException";
|
|||
}
|
||||
}
|
||||
}
|
||||
return GSObjCGetValue(self, aKey, sel, type, size, off);
|
||||
if (sel != 0 || type != NULL)
|
||||
{
|
||||
return GSObjCGetValue(self, aKey, sel, type, size, off);
|
||||
}
|
||||
}
|
||||
[self handleTakeValue: nil forUnboundKey: aKey];
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
|
@ -174,12 +354,7 @@ NSString* const NSUnknownKeyException = @"NSUnknownKeyException";
|
|||
}
|
||||
|
||||
size = [aKey length];
|
||||
if (size < 1)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"takeStoredValue:forKey: ... empty key"];
|
||||
}
|
||||
else
|
||||
if (size > 0)
|
||||
{
|
||||
SEL sel;
|
||||
const char *type;
|
||||
|
@ -228,8 +403,13 @@ NSString* const NSUnknownKeyException = @"NSUnknownKeyException";
|
|||
}
|
||||
}
|
||||
}
|
||||
GSObjCSetValue(self, aKey, anObject, sel, type, size, off);
|
||||
}
|
||||
if (sel != 0 || type != NULL)
|
||||
{
|
||||
GSObjCSetValue(self, aKey, anObject, sel, type, size, off);
|
||||
return;
|
||||
}
|
||||
}
|
||||
[self handleTakeValue: anObject forUnboundKey: aKey];
|
||||
}
|
||||
|
||||
|
||||
|
@ -254,19 +434,14 @@ NSString* const NSUnknownKeyException = @"NSUnknownKeyException";
|
|||
|
||||
- (void) takeValue: (id)anObject forKey: (NSString*)aKey
|
||||
{
|
||||
unsigned size;
|
||||
SEL sel = 0;
|
||||
const char *type = 0;
|
||||
int off;
|
||||
unsigned size = [aKey length];
|
||||
|
||||
size = [aKey length];
|
||||
if (size < 1)
|
||||
GSOnceMLog(@"This method is deprecated, use -setValue:forKey:");
|
||||
if (size > 0)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"takeValue:forKey: ... empty key"];
|
||||
}
|
||||
else
|
||||
{
|
||||
SEL sel;
|
||||
const char *type;
|
||||
int off;
|
||||
const char *name;
|
||||
char buf[size+6];
|
||||
char lo;
|
||||
|
@ -304,8 +479,8 @@ NSString* const NSUnknownKeyException = @"NSUnknownKeyException";
|
|||
}
|
||||
}
|
||||
}
|
||||
GSObjCSetValue(self, aKey, anObject, sel, type, size, off);
|
||||
}
|
||||
GSObjCSetValue(self, aKey, anObject, sel, type, size, off);
|
||||
}
|
||||
|
||||
|
||||
|
@ -313,6 +488,7 @@ NSString* const NSUnknownKeyException = @"NSUnknownKeyException";
|
|||
{
|
||||
NSRange r = [aKey rangeOfString: @"."];
|
||||
|
||||
GSOnceMLog(@"This method is deprecated, use -setValue:forKeyPath:");
|
||||
if (r.length == 0)
|
||||
{
|
||||
[self takeValue: anObject forKey: aKey];
|
||||
|
@ -333,6 +509,7 @@ NSString* const NSUnknownKeyException = @"NSUnknownKeyException";
|
|||
NSNull *null = [NSNull null];
|
||||
NSString *key;
|
||||
|
||||
GSOnceMLog(@"This method is deprecated, use -setValue:forKeyPath:");
|
||||
while ((key = [enumerator nextObject]) != nil)
|
||||
{
|
||||
id obj = [aDictionary objectForKey: key];
|
||||
|
@ -348,28 +525,69 @@ NSString* const NSUnknownKeyException = @"NSUnknownKeyException";
|
|||
|
||||
- (void) unableToSetNilForKey: (NSString*)aKey
|
||||
{
|
||||
GSOnceMLog(@"This method is deprecated, use -setNilValueForKey:");
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"%@ -- %@ 0x%x: Given nil value to set for key \"%@\"",
|
||||
NSStringFromSelector(_cmd), NSStringFromClass([self class]), self, aKey];
|
||||
}
|
||||
|
||||
|
||||
- (id) valueForKey: (NSString*)aKey
|
||||
- (BOOL) validateValue: (id*)aValue
|
||||
forKey: (NSString*)aKey
|
||||
error: (NSError**)anError
|
||||
{
|
||||
unsigned size;
|
||||
NSString *name;
|
||||
const char *str = [aKey cString];
|
||||
SEL sel;
|
||||
BOOL (*imp)(id,SEL,id*,id*);
|
||||
|
||||
size = [aKey length];
|
||||
if (size < 1)
|
||||
if (aValue == 0 || str == 0 || *str == '\0')
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"valueForKey: ... empty key"];
|
||||
return nil;
|
||||
[NSException raise: NSInvalidArgumentException format: @"nil argument"];
|
||||
}
|
||||
name = [NSString stringWithFormat: @"validate%c%s:error:",
|
||||
islower(*str) ? toupper(*str) : *str, str + 1];
|
||||
sel = NSSelectorFromString(name);
|
||||
if (sel != 0
|
||||
&& (imp = (BOOL (*)(id,SEL,id*,id*))[self methodForSelector: sel]) != 0)
|
||||
{
|
||||
return (*imp)(self, sel, aValue, anError);
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) validateValue: (id*)aValue
|
||||
forKeyPath: (NSString*)aKey
|
||||
error: (NSError**)anError
|
||||
{
|
||||
NSRange r = [aKey rangeOfString: @"."];
|
||||
BOOL result;
|
||||
|
||||
if (r.length == 0)
|
||||
{
|
||||
result = [self validateValue: aValue forKey: aKey error: anError];
|
||||
}
|
||||
else
|
||||
{
|
||||
SEL sel = 0;
|
||||
const char *type = NULL;
|
||||
unsigned off;
|
||||
NSString *key = [aKey substringToIndex: r.location];
|
||||
NSString *path = [aKey substringFromIndex: NSMaxRange(r)];
|
||||
|
||||
result = [[self valueForKey: key]
|
||||
validateValue: aValue forKeyPath: path error: anError];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
- (id) valueForKey: (NSString*)aKey
|
||||
{
|
||||
unsigned size;
|
||||
SEL sel = 0;
|
||||
int off;
|
||||
const char *type = NULL;
|
||||
|
||||
size = [aKey length];
|
||||
if (size > 0)
|
||||
{
|
||||
const char *name;
|
||||
char buf[size+5];
|
||||
char lo;
|
||||
|
@ -390,36 +608,40 @@ NSString* const NSUnknownKeyException = @"NSUnknownKeyException";
|
|||
sel = GSSelectorFromName(name);
|
||||
if (sel == 0 || [self respondsToSelector: sel] == NO)
|
||||
{
|
||||
buf[4] = hi;
|
||||
name = buf; // _getKey
|
||||
sel = GSSelectorFromName(name);
|
||||
if (sel == 0 || [self respondsToSelector: sel] == NO)
|
||||
{
|
||||
buf[4] = lo;
|
||||
buf[3] = '_';
|
||||
name = &buf[3]; // _key
|
||||
sel = GSSelectorFromName(name);
|
||||
if (sel == 0 || [self respondsToSelector: sel] == NO)
|
||||
{
|
||||
sel = 0;
|
||||
}
|
||||
}
|
||||
sel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (sel == 0 && [[self class] accessInstanceVariablesDirectly] == YES)
|
||||
{
|
||||
buf[4] = lo;
|
||||
buf[3] = '_';
|
||||
name = &buf[4]; // key
|
||||
if (GSObjCFindVariable(self, name, &type, &size, &off) == NO)
|
||||
buf[4] = hi;
|
||||
name = buf; // _getKey
|
||||
sel = GSSelectorFromName(name);
|
||||
if (sel == 0 || [self respondsToSelector: sel] == NO)
|
||||
{
|
||||
buf[4] = lo;
|
||||
buf[3] = '_';
|
||||
name = &buf[3]; // _key
|
||||
GSObjCFindVariable(self, name, &type, &size, &off);
|
||||
sel = GSSelectorFromName(name);
|
||||
if (sel == 0 || [self respondsToSelector: sel] == NO)
|
||||
{
|
||||
sel = 0;
|
||||
}
|
||||
}
|
||||
if (sel == 0)
|
||||
{
|
||||
buf[4] = lo;
|
||||
buf[3] = '_';
|
||||
name = &buf[4]; // key
|
||||
if (GSObjCFindVariable(self, name, &type, &size, &off) == NO)
|
||||
{
|
||||
name = &buf[3]; // _key
|
||||
GSObjCFindVariable(self, name, &type, &size, &off);
|
||||
}
|
||||
}
|
||||
}
|
||||
return GSObjCGetValue(self, aKey, sel, type, size, off);
|
||||
}
|
||||
return GSObjCGetValue(self, aKey, sel, type, size, off);
|
||||
}
|
||||
|
||||
|
||||
|
@ -443,6 +665,33 @@ NSString* const NSUnknownKeyException = @"NSUnknownKeyException";
|
|||
}
|
||||
|
||||
|
||||
- (id) valueForUndefinedKey: (NSString*)aKey
|
||||
{
|
||||
NSDictionary *dict;
|
||||
NSException *exp;
|
||||
|
||||
/* Backward compatibility hack */
|
||||
if ([self methodForSelector: @selector(handleQueryWithUnboundKey:)]
|
||||
== [NSObject instanceMethodForSelector:
|
||||
@selector(handleQueryWithUnboundKey:)])
|
||||
{
|
||||
return [self handleQueryWithUnboundKey: aKey];
|
||||
}
|
||||
dict = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
self,
|
||||
@"NSTargetObjectUserInfoKey",
|
||||
(aKey ? aKey : @"(nil)"),
|
||||
@"NSUnknownUserInfoKey",
|
||||
nil];
|
||||
exp = [NSException exceptionWithName: NSUnknownKeyException
|
||||
reason: @"Unable to find value for key"
|
||||
userInfo: dict];
|
||||
|
||||
[exp raise];
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
- (NSDictionary*) valuesForKeys: (NSArray*)keys
|
||||
{
|
||||
NSMutableDictionary *dict;
|
||||
|
|
Loading…
Reference in a new issue