2002-02-25 07:05:58 +00:00
|
|
|
/** Implementation of KeyValueCoding for GNUStep
|
|
|
|
Copyright (C) 2000,2002 Free Software Foundation, Inc.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2002-02-25 07:05:58 +00:00
|
|
|
Written by: Richard Frith-Macdonald <rfm@gnu.org>
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2002-02-25 07:05:58 +00:00
|
|
|
This file is part of the GNUstep Base Library.
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
2007-09-14 11:36:11 +00:00
|
|
|
modify it under the terms of the GNU Lesser General Public
|
2002-02-25 07:05:58 +00:00
|
|
|
License as published by the Free Software Foundation; either
|
2008-06-08 10:38:33 +00:00
|
|
|
version 2 of the License, or (at your option) any later version.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2002-02-25 07:05:58 +00:00
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2007-09-14 11:36:11 +00:00
|
|
|
You should have received a copy of the GNU Lesser General Public
|
2002-02-25 07:05:58 +00:00
|
|
|
License along with this library; if not, write to the Free
|
2006-02-27 09:35:19 +00:00
|
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02111 USA.
|
2002-02-25 07:05:58 +00:00
|
|
|
|
|
|
|
<title>NSKeyValueCoding informal protocol reference</title>
|
|
|
|
$Date$ $Revision$
|
2005-02-22 11:22:44 +00:00
|
|
|
*/
|
2002-02-25 07:05:58 +00:00
|
|
|
|
2003-06-07 01:24:41 +00:00
|
|
|
#include "config.h"
|
|
|
|
#include "Foundation/NSArray.h"
|
2007-11-29 20:56:11 +00:00
|
|
|
#include "Foundation/NSAutoreleasePool.h"
|
|
|
|
#include "Foundation/NSDebug.h"
|
2007-11-29 20:53:26 +00:00
|
|
|
#include "Foundation/NSDictionary.h"
|
|
|
|
#include "Foundation/NSEnumerator.h"
|
2003-06-07 01:24:41 +00:00
|
|
|
#include "Foundation/NSException.h"
|
|
|
|
#include "Foundation/NSKeyValueCoding.h"
|
2007-11-29 20:56:11 +00:00
|
|
|
#include "Foundation/NSMethodSignature.h"
|
2003-06-07 01:24:41 +00:00
|
|
|
#include "Foundation/NSNull.h"
|
2007-11-29 20:56:11 +00:00
|
|
|
#include "Foundation/NSObjCRuntime.h"
|
|
|
|
#include "Foundation/NSSet.h"
|
|
|
|
#include "Foundation/NSString.h"
|
|
|
|
#include "Foundation/NSValue.h"
|
|
|
|
#include "Foundation/NSZone.h"
|
2002-02-25 07:05:58 +00:00
|
|
|
|
2007-07-10 17:16:31 +00:00
|
|
|
/* For the NSKeyValueMutableArray and NSKeyValueMutableSet classes
|
|
|
|
*/
|
|
|
|
#include "NSKeyValueMutableArray.m"
|
|
|
|
#include "NSKeyValueMutableSet.m"
|
|
|
|
|
2007-06-08 08:04:14 +00:00
|
|
|
/* For backward compatibility NSUndefinedKeyException is actually the same
|
|
|
|
* as the older NSUnknownKeyException
|
|
|
|
*/
|
|
|
|
NSString* const NSUnknownKeyException = @"NSUnknownKeyException";
|
|
|
|
NSString* const NSUndefinedKeyException = @"NSUnknownKeyException";
|
2002-02-25 07:05:58 +00:00
|
|
|
|
2006-02-27 09:35:19 +00:00
|
|
|
|
2007-11-29 20:56:11 +00:00
|
|
|
/* this should move into autoconf once it's accepted */
|
|
|
|
#define WANT_DEPRECATED_KVC_COMPAT 1
|
|
|
|
|
2008-03-02 08:23:51 +00:00
|
|
|
#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
|
2007-11-29 20:56:11 +00:00
|
|
|
|
2006-02-27 09:35:19 +00:00
|
|
|
static void
|
|
|
|
SetValueForKey(NSObject *self, id anObject, const char *key, unsigned size)
|
|
|
|
{
|
|
|
|
SEL sel = 0;
|
|
|
|
const char *type = 0;
|
|
|
|
int off;
|
|
|
|
|
|
|
|
if (size > 0)
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
char buf[size+6];
|
|
|
|
char lo;
|
|
|
|
char hi;
|
|
|
|
|
|
|
|
strcpy(buf, "_set");
|
|
|
|
strcpy(&buf[4], key);
|
|
|
|
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
|
|
|
|
{
|
2007-06-06 09:18:54 +00:00
|
|
|
GSOnceFLog(@"Key-value access using _setKey: is deprecated:");
|
2006-02-27 09:35:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
GSObjCSetVal(self, key, anObject, sel, type, size, off);
|
|
|
|
}
|
|
|
|
|
|
|
|
static id ValueForKey(NSObject *self, const char *key, unsigned size)
|
|
|
|
{
|
|
|
|
SEL sel = 0;
|
|
|
|
int off;
|
|
|
|
const char *type = NULL;
|
|
|
|
|
|
|
|
if (size > 0)
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
char buf[size+5];
|
|
|
|
char lo;
|
|
|
|
char hi;
|
|
|
|
|
|
|
|
strcpy(buf, "_get");
|
|
|
|
strcpy(&buf[4], key);
|
|
|
|
lo = buf[4];
|
|
|
|
hi = islower(lo) ? toupper(lo) : lo;
|
|
|
|
buf[4] = hi;
|
|
|
|
|
|
|
|
name = &buf[1]; // getKey
|
|
|
|
sel = GSSelectorFromName(name);
|
|
|
|
if (sel == 0 || [self respondsToSelector: sel] == NO)
|
|
|
|
{
|
|
|
|
buf[4] = lo;
|
|
|
|
name = &buf[4]; // key
|
|
|
|
sel = GSSelectorFromName(name);
|
|
|
|
if (sel == 0 || [self respondsToSelector: sel] == NO)
|
|
|
|
{
|
|
|
|
sel = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sel == 0 && [[self class] accessInstanceVariablesDirectly] == YES)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (sel == 0)
|
|
|
|
{
|
|
|
|
buf[4] = lo;
|
|
|
|
buf[3] = '_';
|
2008-03-16 07:34:25 +00:00
|
|
|
name = &buf[3]; // _key
|
2006-02-27 09:35:19 +00:00
|
|
|
if (GSObjCFindVariable(self, name, &type, &size, &off) == NO)
|
|
|
|
{
|
2008-03-16 07:34:25 +00:00
|
|
|
name = &buf[4]; // key
|
2006-02-27 09:35:19 +00:00
|
|
|
GSObjCFindVariable(self, name, &type, &size, &off);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return GSObjCGetVal(self, key, sel, type, size, off);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-09-19 23:24:36 +00:00
|
|
|
@implementation NSObject(KeyValueCoding)
|
|
|
|
|
2002-02-25 07:05:58 +00:00
|
|
|
+ (BOOL) accessInstanceVariablesDirectly
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2004-09-19 23:24:36 +00:00
|
|
|
|
2005-03-02 11:46:21 +00:00
|
|
|
- (NSDictionary*) dictionaryWithValuesForKeys: (NSArray*)keys
|
|
|
|
{
|
|
|
|
NSMutableDictionary *dictionary;
|
|
|
|
NSEnumerator *enumerator;
|
|
|
|
id key;
|
2007-11-29 20:56:11 +00:00
|
|
|
#ifdef WANT_DEPRECATED_KVC_COMPAT
|
|
|
|
static IMP o = 0;
|
|
|
|
|
|
|
|
/* Backward compatibility hack */
|
|
|
|
if (o == 0)
|
|
|
|
{
|
|
|
|
o = [NSObject instanceMethodForSelector:
|
|
|
|
@selector(valuesForKeys:)];
|
|
|
|
}
|
|
|
|
if ([self methodForSelector: @selector(valuesForKeys:)] != o)
|
|
|
|
{
|
|
|
|
return [self valuesForKeys: keys];
|
|
|
|
}
|
|
|
|
#endif
|
2005-03-02 11:46:21 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2007-07-10 17:16:31 +00:00
|
|
|
- (NSMutableSet*) mutableSetValueForKey: (NSString*)aKey
|
|
|
|
{
|
2007-07-14 04:34:00 +00:00
|
|
|
return [NSKeyValueMutableSet setForKey: aKey ofObject: self];
|
2007-07-10 17:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSMutableSet*) mutableSetValueForKeyPath: (NSString*)aKey
|
|
|
|
{
|
2008-03-13 12:10:01 +00:00
|
|
|
NSRange r = [aKey rangeOfString: @"."];
|
2007-07-10 17:16:31 +00:00
|
|
|
|
2008-03-13 12:10:01 +00:00
|
|
|
if (r.length == 0)
|
2007-07-10 17:16:31 +00:00
|
|
|
{
|
2008-03-13 12:10:01 +00:00
|
|
|
return [self mutableSetValueForKey: aKey];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSString *key = [aKey substringToIndex: r.location];
|
|
|
|
NSString *path = [aKey substringFromIndex: NSMaxRange(r)];
|
|
|
|
|
|
|
|
return [[self valueForKey: key] mutableSetValueForKeyPath: path];
|
2007-07-10 17:16:31 +00:00
|
|
|
}
|
|
|
|
}
|
2005-03-02 11:46:21 +00:00
|
|
|
|
|
|
|
- (NSMutableArray*) mutableArrayValueForKey: (NSString*)aKey
|
|
|
|
{
|
2007-07-14 04:34:00 +00:00
|
|
|
return [NSKeyValueMutableArray arrayForKey: aKey ofObject: self];
|
2005-03-02 11:46:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSMutableArray*) mutableArrayValueForKeyPath: (NSString*)aKey
|
|
|
|
{
|
2008-03-13 12:10:01 +00:00
|
|
|
NSRange r = [aKey rangeOfString: @"."];
|
2007-07-10 17:16:31 +00:00
|
|
|
|
2008-03-13 12:10:01 +00:00
|
|
|
if (r.length == 0)
|
2007-07-10 17:16:31 +00:00
|
|
|
{
|
2008-03-13 12:10:01 +00:00
|
|
|
return [self mutableArrayValueForKey: aKey];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSString *key = [aKey substringToIndex: r.location];
|
|
|
|
NSString *path = [aKey substringFromIndex: NSMaxRange(r)];
|
|
|
|
|
|
|
|
return [[self valueForKey: key] mutableArrayValueForKeyPath: path];
|
2007-07-10 17:16:31 +00:00
|
|
|
}
|
2005-03-02 11:46:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setNilValueForKey: (NSString*)aKey
|
|
|
|
{
|
2007-11-29 20:56:11 +00:00
|
|
|
#ifdef WANT_DEPRECATED_KVC_COMPAT
|
2005-03-02 13:39:33 +00:00
|
|
|
static IMP o = 0;
|
|
|
|
|
2005-03-02 11:46:21 +00:00
|
|
|
/* Backward compatibility hack */
|
2005-03-02 13:39:33 +00:00
|
|
|
if (o == 0)
|
|
|
|
{
|
|
|
|
o = [NSObject instanceMethodForSelector:
|
|
|
|
@selector(unableToSetNilForKey:)];
|
|
|
|
}
|
|
|
|
if ([self methodForSelector: @selector(unableToSetNilForKey:)] != o)
|
2005-03-02 11:46:21 +00:00
|
|
|
{
|
|
|
|
[self unableToSetNilForKey: aKey];
|
2007-11-29 20:56:11 +00:00
|
|
|
return;
|
2005-03-02 11:46:21 +00:00
|
|
|
}
|
2007-11-29 20:56:11 +00:00
|
|
|
#endif
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
format: @"%@ -- %@ 0x%x: Given nil value to set for key \"%@\"",
|
|
|
|
NSStringFromSelector(_cmd), NSStringFromClass([self class]),
|
|
|
|
self, aKey];
|
2005-03-02 11:46:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void) setValue: (id)anObject forKey: (NSString*)aKey
|
|
|
|
{
|
2007-06-06 09:18:54 +00:00
|
|
|
unsigned size = [aKey length] * 8;
|
2006-02-27 09:35:19 +00:00
|
|
|
char key[size+1];
|
2007-11-29 20:56:11 +00:00
|
|
|
#ifdef WANT_DEPRECATED_KVC_COMPAT
|
2008-03-02 08:23:51 +00:00
|
|
|
IMP o = [self methodForSelector: @selector(takeValue:forKey:)];
|
2007-11-29 20:56:11 +00:00
|
|
|
|
2008-03-02 08:23:51 +00:00
|
|
|
setupCompat();
|
|
|
|
if (o != takeValue && o != takeValueKVO)
|
2007-11-29 20:56:11 +00:00
|
|
|
{
|
2008-03-05 12:26:13 +00:00
|
|
|
(*o)(self, @selector(takeValue:forKey:), anObject, aKey);
|
2007-11-29 20:56:11 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
2005-03-02 11:46:21 +00:00
|
|
|
|
2006-02-27 09:35:19 +00:00
|
|
|
[aKey getCString: key
|
|
|
|
maxLength: size+1
|
2007-06-06 09:18:54 +00:00
|
|
|
encoding: NSUTF8StringEncoding];
|
|
|
|
size = strlen(key);
|
2006-02-27 09:35:19 +00:00
|
|
|
SetValueForKey(self, anObject, key, size);
|
2005-03-02 11:46:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void) setValue: (id)anObject forKeyPath: (NSString*)aKey
|
|
|
|
{
|
2008-03-13 12:10:01 +00:00
|
|
|
NSRange r = [aKey rangeOfString: @"."];
|
2007-11-29 20:56:11 +00:00
|
|
|
#ifdef WANT_DEPRECATED_KVC_COMPAT
|
2008-03-02 08:23:51 +00:00
|
|
|
IMP o = [self methodForSelector: @selector(takeValue:forKeyPath:)];
|
2007-11-29 20:56:11 +00:00
|
|
|
|
2008-03-02 08:23:51 +00:00
|
|
|
setupCompat();
|
|
|
|
if (o != takePath && o != takePathKVO)
|
2007-11-29 20:56:11 +00:00
|
|
|
{
|
2008-03-02 08:23:51 +00:00
|
|
|
(*o)(self, @selector(takeValue:forKeyPath:), anObject, aKey);
|
2007-11-29 20:56:11 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
2006-02-27 09:35:19 +00:00
|
|
|
|
2008-03-13 12:10:01 +00:00
|
|
|
if (r.length == 0)
|
2005-03-02 11:46:21 +00:00
|
|
|
{
|
2008-03-13 12:10:01 +00:00
|
|
|
[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];
|
2005-03-02 11:46:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void) setValue: (id)anObject forUndefinedKey: (NSString*)aKey
|
|
|
|
{
|
|
|
|
NSDictionary *dict;
|
|
|
|
NSException *exp;
|
2007-11-29 20:56:11 +00:00
|
|
|
#ifdef WANT_DEPRECATED_KVC_COMPAT
|
2005-03-02 13:39:33 +00:00
|
|
|
static IMP o = 0;
|
2005-03-02 11:46:21 +00:00
|
|
|
|
|
|
|
/* Backward compatibility hack */
|
2005-03-02 13:39:33 +00:00
|
|
|
if (o == 0)
|
|
|
|
{
|
|
|
|
o = [NSObject instanceMethodForSelector:
|
|
|
|
@selector(handleTakeValue:forUnboundKey:)];
|
|
|
|
}
|
|
|
|
if ([self methodForSelector: @selector(handleTakeValue:forUnboundKey:)] != o)
|
2005-03-02 11:46:21 +00:00
|
|
|
{
|
|
|
|
[self handleTakeValue: anObject forUnboundKey: aKey];
|
2006-04-26 12:24:03 +00:00
|
|
|
return;
|
2005-03-02 11:46:21 +00:00
|
|
|
}
|
2007-11-29 20:56:11 +00:00
|
|
|
#endif
|
2005-03-02 11:46:21 +00:00
|
|
|
|
|
|
|
dict = [NSDictionary dictionaryWithObjectsAndKeys:
|
2006-05-15 12:07:35 +00:00
|
|
|
(anObject ? (id)anObject : (id)@"(nil)"), @"NSTargetObjectUserInfoKey",
|
|
|
|
(aKey ? (id)aKey : (id)@"(nil)"), @"NSUnknownUserInfoKey",
|
|
|
|
nil];
|
2007-06-08 08:04:14 +00:00
|
|
|
exp = [NSException exceptionWithName: NSUndefinedKeyException
|
2005-03-02 11:46:21 +00:00
|
|
|
reason: @"Unable to set nil value for key"
|
|
|
|
userInfo: dict];
|
2003-03-23 07:06:27 +00:00
|
|
|
[exp raise];
|
2002-02-25 07:05:58 +00:00
|
|
|
}
|
|
|
|
|
2004-09-19 23:24:36 +00:00
|
|
|
|
2005-03-02 11:46:21 +00:00
|
|
|
- (void) setValuesForKeysWithDictionary: (NSDictionary*)aDictionary
|
|
|
|
{
|
2007-11-29 20:56:11 +00:00
|
|
|
NSEnumerator *enumerator;
|
2005-03-02 11:46:21 +00:00
|
|
|
NSString *key;
|
2007-11-29 20:56:11 +00:00
|
|
|
#ifdef WANT_DEPRECATED_KVC_COMPAT
|
|
|
|
static IMP o = 0;
|
2005-03-02 11:46:21 +00:00
|
|
|
|
2007-11-29 20:56:11 +00:00
|
|
|
/* Backward compatibility hack */
|
|
|
|
if (o == 0)
|
|
|
|
{
|
|
|
|
o = [NSObject instanceMethodForSelector:
|
|
|
|
@selector(takeValuesFromDictionary:)];
|
|
|
|
}
|
|
|
|
if ([self methodForSelector: @selector(takeValuesFromDictionary:)] != o)
|
|
|
|
{
|
|
|
|
[self takeValuesFromDictionary: aDictionary];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
enumerator = [aDictionary keyEnumerator];
|
2005-03-02 11:46:21 +00:00
|
|
|
while ((key = [enumerator nextObject]) != nil)
|
|
|
|
{
|
|
|
|
[self setValue: [aDictionary objectForKey: key] forKey: key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-29 20:56:11 +00:00
|
|
|
- (BOOL) validateValue: (id*)aValue
|
|
|
|
forKey: (NSString*)aKey
|
|
|
|
error: (NSError**)anError
|
|
|
|
{
|
|
|
|
unsigned size;
|
|
|
|
|
|
|
|
if (aValue == 0 || (size = [aKey length] * 8) == 0)
|
|
|
|
{
|
|
|
|
[NSException raise: NSInvalidArgumentException format: @"nil argument"];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char name[size+16];
|
|
|
|
SEL sel;
|
|
|
|
BOOL (*imp)(id,SEL,id*,id*);
|
|
|
|
|
|
|
|
strcpy(name, "validate");
|
|
|
|
[aKey getCString: &name[8]
|
|
|
|
maxLength: size+1
|
|
|
|
encoding: NSUTF8StringEncoding];
|
|
|
|
size = strlen(&name[8]);
|
|
|
|
strcpy(&name[size+8], ":error:");
|
|
|
|
if (islower(name[8]))
|
|
|
|
{
|
|
|
|
name[8] = toupper(name[8]);
|
|
|
|
}
|
|
|
|
sel = GSSelectorFromName(name);
|
2009-02-27 12:54:15 +00:00
|
|
|
if (sel != 0 && [self respondsToSelector: sel] == YES)
|
2007-11-29 20:56:11 +00:00
|
|
|
{
|
2009-02-27 12:54:15 +00:00
|
|
|
imp = (BOOL (*)(id,SEL,id*,id*))[self methodForSelector: sel];
|
2007-11-29 20:56:11 +00:00
|
|
|
return (*imp)(self, sel, aValue, anError);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) validateValue: (id*)aValue
|
|
|
|
forKeyPath: (NSString*)aKey
|
|
|
|
error: (NSError**)anError
|
|
|
|
{
|
2008-03-13 12:10:01 +00:00
|
|
|
NSRange r = [aKey rangeOfString: @"."];
|
2007-11-29 20:56:11 +00:00
|
|
|
|
2008-03-13 12:10:01 +00:00
|
|
|
if (r.length == 0)
|
2007-11-29 20:56:11 +00:00
|
|
|
{
|
2008-03-13 12:10:01 +00:00
|
|
|
return [self validateValue: aValue forKey: aKey error: anError];
|
2007-11-29 20:56:11 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-03-13 12:10:01 +00:00
|
|
|
NSString *key = [aKey substringToIndex: r.location];
|
|
|
|
NSString *path = [aKey substringFromIndex: NSMaxRange(r)];
|
2007-11-29 20:56:11 +00:00
|
|
|
|
2008-03-13 12:10:01 +00:00
|
|
|
return [[self valueForKey: key] validateValue: aValue
|
|
|
|
forKeyPath: path
|
|
|
|
error: anError];
|
2007-11-29 20:56:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (id) valueForKey: (NSString*)aKey
|
|
|
|
{
|
|
|
|
unsigned size = [aKey length] * 8;
|
|
|
|
char key[size+1];
|
|
|
|
|
|
|
|
[aKey getCString: key
|
|
|
|
maxLength: size+1
|
|
|
|
encoding: NSUTF8StringEncoding];
|
|
|
|
size = strlen(key);
|
|
|
|
return ValueForKey(self, key, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (id) valueForKeyPath: (NSString*)aKey
|
|
|
|
{
|
2008-03-13 12:10:01 +00:00
|
|
|
NSRange r = [aKey rangeOfString: @"."];
|
2007-11-29 20:56:11 +00:00
|
|
|
|
2008-03-13 12:10:01 +00:00
|
|
|
if (r.length == 0)
|
2007-11-29 20:56:11 +00:00
|
|
|
{
|
2008-03-13 12:10:01 +00:00
|
|
|
return [self valueForKey: aKey];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSString *key = [aKey substringToIndex: r.location];
|
|
|
|
NSString *path = [aKey substringFromIndex: NSMaxRange(r)];
|
|
|
|
|
|
|
|
return [[self valueForKey: key] valueForKeyPath: path];
|
2007-11-29 20:56:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (id) valueForUndefinedKey: (NSString*)aKey
|
|
|
|
{
|
|
|
|
NSDictionary *dict;
|
|
|
|
NSException *exp;
|
|
|
|
NSString *reason;
|
|
|
|
#ifdef WANT_DEPRECATED_KVC_COMPAT
|
|
|
|
static IMP o = 0;
|
|
|
|
|
|
|
|
/* Backward compatibility hack */
|
|
|
|
if (o == 0)
|
|
|
|
{
|
|
|
|
o = [NSObject instanceMethodForSelector:
|
|
|
|
@selector(handleQueryWithUnboundKey:)];
|
|
|
|
}
|
|
|
|
if ([self methodForSelector: @selector(handleQueryWithUnboundKey:)] != o)
|
|
|
|
{
|
|
|
|
return [self handleQueryWithUnboundKey: aKey];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
dict = [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
self, @"NSTargetObjectUserInfoKey",
|
|
|
|
(aKey ? (id)aKey : (id)@"(nil)"), @"NSUnknownUserInfoKey",
|
|
|
|
nil];
|
|
|
|
reason = [NSString stringWithFormat:
|
|
|
|
@"Unable to find value for key \"%@\" of object %@ (%@)",
|
|
|
|
aKey, self, [self class]];
|
|
|
|
exp = [NSException exceptionWithName: NSUndefinedKeyException
|
|
|
|
reason: reason
|
|
|
|
userInfo: dict];
|
|
|
|
|
|
|
|
[exp raise];
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef WANT_DEPRECATED_KVC_COMPAT
|
|
|
|
|
|
|
|
+ (BOOL) useStoredAccessor
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2002-02-25 07:05:58 +00:00
|
|
|
- (id) storedValueForKey: (NSString*)aKey
|
|
|
|
{
|
|
|
|
unsigned size;
|
|
|
|
|
|
|
|
if ([[self class] useStoredAccessor] == NO)
|
|
|
|
{
|
|
|
|
return [self valueForKey: aKey];
|
|
|
|
}
|
|
|
|
|
2007-06-06 09:18:54 +00:00
|
|
|
size = [aKey length] * 8;
|
2005-03-02 11:46:21 +00:00
|
|
|
if (size > 0)
|
2002-02-25 07:05:58 +00:00
|
|
|
{
|
|
|
|
SEL sel = 0;
|
|
|
|
const char *type = NULL;
|
2005-03-02 11:46:21 +00:00
|
|
|
int off;
|
2002-02-25 07:05:58 +00:00
|
|
|
const char *name;
|
2006-02-27 09:35:19 +00:00
|
|
|
char key[size+1];
|
2002-02-25 07:05:58 +00:00
|
|
|
char buf[size+5];
|
|
|
|
char lo;
|
|
|
|
char hi;
|
|
|
|
|
|
|
|
strcpy(buf, "_get");
|
2006-02-27 09:35:19 +00:00
|
|
|
[aKey getCString: key
|
|
|
|
maxLength: size+1
|
2007-06-06 09:18:54 +00:00
|
|
|
encoding: NSUTF8StringEncoding];
|
|
|
|
size = strlen(key);
|
2006-02-27 09:35:19 +00:00
|
|
|
strcpy(&buf[4], key);
|
2002-02-25 07:05:58 +00:00
|
|
|
lo = buf[4];
|
|
|
|
hi = islower(lo) ? toupper(lo) : lo;
|
|
|
|
buf[4] = hi;
|
|
|
|
|
|
|
|
name = buf; // _getKey
|
2008-12-01 18:38:58 +00:00
|
|
|
sel = GSSelectorFromName(name);
|
2002-02-25 07:05:58 +00:00
|
|
|
if (sel == 0 || [self respondsToSelector: sel] == NO)
|
|
|
|
{
|
|
|
|
buf[3] = '_';
|
|
|
|
buf[4] = lo;
|
|
|
|
name = &buf[3]; // _key
|
2008-12-01 18:38:58 +00:00
|
|
|
sel = GSSelectorFromName(name);
|
2002-02-25 07:05:58 +00:00
|
|
|
if (sel == 0 || [self respondsToSelector: sel] == NO)
|
|
|
|
{
|
|
|
|
sel = 0;
|
2005-02-22 11:22:44 +00:00
|
|
|
}
|
2002-02-25 07:05:58 +00:00
|
|
|
}
|
|
|
|
if (sel == 0)
|
|
|
|
{
|
|
|
|
if ([[self class] accessInstanceVariablesDirectly] == YES)
|
|
|
|
{
|
|
|
|
// _key
|
2002-11-29 14:21:09 +00:00
|
|
|
if (GSObjCFindVariable(self, name, &type, &size, &off) == NO)
|
2002-02-25 07:05:58 +00:00
|
|
|
{
|
|
|
|
name = &buf[4]; // key
|
2002-11-29 14:21:09 +00:00
|
|
|
GSObjCFindVariable(self, name, &type, &size, &off);
|
2002-02-25 07:05:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (type == NULL)
|
|
|
|
{
|
|
|
|
buf[3] = 't';
|
|
|
|
buf[4] = hi;
|
|
|
|
name = &buf[1]; // getKey
|
2008-12-01 18:38:58 +00:00
|
|
|
sel = GSSelectorFromName(name);
|
2002-02-25 07:05:58 +00:00
|
|
|
if (sel == 0 || [self respondsToSelector: sel] == NO)
|
|
|
|
{
|
|
|
|
buf[4] = lo;
|
|
|
|
name = &buf[4]; // key
|
2008-12-01 18:38:58 +00:00
|
|
|
sel = GSSelectorFromName(name);
|
2002-02-25 07:05:58 +00:00
|
|
|
if (sel == 0 || [self respondsToSelector: sel] == NO)
|
|
|
|
{
|
|
|
|
sel = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-03-02 11:46:21 +00:00
|
|
|
if (sel != 0 || type != NULL)
|
|
|
|
{
|
2006-02-27 09:35:19 +00:00
|
|
|
return GSObjCGetVal(self, key, sel, type, size, off);
|
2005-03-02 11:46:21 +00:00
|
|
|
}
|
2002-02-25 07:05:58 +00:00
|
|
|
}
|
2005-03-02 11:46:21 +00:00
|
|
|
[self handleTakeValue: nil forUnboundKey: aKey];
|
|
|
|
return nil;
|
2002-02-25 07:05:58 +00:00
|
|
|
}
|
|
|
|
|
2004-09-19 23:24:36 +00:00
|
|
|
|
2002-02-25 07:05:58 +00:00
|
|
|
- (void) takeStoredValue: (id)anObject forKey: (NSString*)aKey
|
|
|
|
{
|
|
|
|
unsigned size;
|
|
|
|
|
|
|
|
if ([[self class] useStoredAccessor] == NO)
|
|
|
|
{
|
|
|
|
[self takeValue: anObject forKey: aKey];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-06-06 09:18:54 +00:00
|
|
|
size = [aKey length] * 8;
|
2005-03-02 11:46:21 +00:00
|
|
|
if (size > 0)
|
2002-02-25 07:05:58 +00:00
|
|
|
{
|
|
|
|
SEL sel;
|
|
|
|
const char *type;
|
|
|
|
int off;
|
|
|
|
const char *name;
|
2006-02-27 09:35:19 +00:00
|
|
|
char key[size+1];
|
2002-02-25 07:05:58 +00:00
|
|
|
char buf[size+6];
|
|
|
|
char lo;
|
|
|
|
char hi;
|
|
|
|
|
|
|
|
strcpy(buf, "_set");
|
2006-02-27 09:35:19 +00:00
|
|
|
[aKey getCString: key
|
|
|
|
maxLength: size+1
|
2007-06-06 09:18:54 +00:00
|
|
|
encoding: NSUTF8StringEncoding];
|
|
|
|
size = strlen(key);
|
2006-02-27 09:35:19 +00:00
|
|
|
strcpy(&buf[4], key);
|
2002-02-25 07:05:58 +00:00
|
|
|
lo = buf[4];
|
|
|
|
hi = islower(lo) ? toupper(lo) : lo;
|
|
|
|
buf[4] = hi;
|
|
|
|
buf[size+4] = ':';
|
2002-02-27 09:01:32 +00:00
|
|
|
buf[size+5] = '\0';
|
2002-02-25 07:05:58 +00:00
|
|
|
|
|
|
|
name = buf; // _setKey:
|
|
|
|
type = NULL;
|
|
|
|
sel = GSSelectorFromName(name);
|
|
|
|
if (sel == 0 || [self respondsToSelector: sel] == NO)
|
|
|
|
{
|
|
|
|
sel = 0;
|
|
|
|
if ([[self class] accessInstanceVariablesDirectly] == YES)
|
|
|
|
{
|
|
|
|
buf[size+4] = '\0';
|
|
|
|
buf[4] = lo;
|
|
|
|
buf[3] = '_';
|
|
|
|
name = &buf[3]; // _key
|
2002-11-29 14:21:09 +00:00
|
|
|
if (GSObjCFindVariable(self, name, &type, &size, &off) == NO)
|
2002-02-25 07:05:58 +00:00
|
|
|
{
|
|
|
|
name = &buf[4]; // key
|
2002-11-29 14:21:09 +00:00
|
|
|
GSObjCFindVariable(self, name, &type, &size, &off);
|
2002-02-25 07:05:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (type == NULL)
|
|
|
|
{
|
|
|
|
buf[size+4] = ':';
|
|
|
|
buf[4] = hi;
|
|
|
|
buf[3] = 't';
|
|
|
|
name = &buf[1]; // setKey:
|
|
|
|
sel = GSSelectorFromName(name);
|
|
|
|
if (sel == 0 || [self respondsToSelector: sel] == NO)
|
|
|
|
{
|
|
|
|
sel = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-03-02 11:46:21 +00:00
|
|
|
if (sel != 0 || type != NULL)
|
|
|
|
{
|
2006-02-27 09:35:19 +00:00
|
|
|
GSObjCSetVal(self, key, anObject, sel, type, size, off);
|
2005-03-02 11:46:21 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
[self handleTakeValue: anObject forUnboundKey: aKey];
|
2002-02-25 07:05:58 +00:00
|
|
|
}
|
|
|
|
|
2004-09-19 23:24:36 +00:00
|
|
|
|
2003-02-19 14:42:07 +00:00
|
|
|
- (void) takeStoredValuesFromDictionary: (NSDictionary*)aDictionary
|
|
|
|
{
|
|
|
|
NSEnumerator *enumerator = [aDictionary keyEnumerator];
|
|
|
|
NSNull *null = [NSNull null];
|
|
|
|
NSString *key;
|
|
|
|
|
|
|
|
while ((key = [enumerator nextObject]) != nil)
|
|
|
|
{
|
|
|
|
id obj = [aDictionary objectForKey: key];
|
|
|
|
|
|
|
|
if (obj == null)
|
|
|
|
{
|
|
|
|
obj = nil;
|
|
|
|
}
|
|
|
|
[self takeStoredValue: obj forKey: key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-29 20:56:11 +00:00
|
|
|
- (id) handleQueryWithUnboundKey: (NSString*)aKey
|
|
|
|
{
|
|
|
|
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
self, @"NSTargetObjectUserInfoKey",
|
|
|
|
(aKey ? (id)aKey : (id)@"(nil)"), @"NSUnknownUserInfoKey",
|
|
|
|
nil];
|
|
|
|
NSException *exp = [NSException exceptionWithName: NSUndefinedKeyException
|
|
|
|
reason: @"Unable to find value for key"
|
|
|
|
userInfo: dict];
|
|
|
|
|
|
|
|
GSOnceMLog(@"This method is deprecated, use -valueForUndefinedKey:");
|
|
|
|
[exp raise];
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void) handleTakeValue: (id)anObject forUnboundKey: (NSString*)aKey
|
|
|
|
{
|
|
|
|
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
(anObject ? (id)anObject : (id)@"(nil)"), @"NSTargetObjectUserInfoKey",
|
|
|
|
(aKey ? (id)aKey : (id)@"(nil)"), @"NSUnknownUserInfoKey",
|
|
|
|
nil];
|
|
|
|
NSException *exp = [NSException exceptionWithName: NSUndefinedKeyException
|
|
|
|
reason: @"Unable to set value for key"
|
|
|
|
userInfo: dict];
|
|
|
|
GSOnceMLog(@"This method is deprecated, use -setValue:forUndefinedKey:");
|
|
|
|
[exp raise];
|
|
|
|
}
|
|
|
|
|
2004-09-19 23:24:36 +00:00
|
|
|
|
2002-02-25 07:05:58 +00:00
|
|
|
- (void) takeValue: (id)anObject forKey: (NSString*)aKey
|
|
|
|
{
|
2005-03-02 11:46:21 +00:00
|
|
|
SEL sel = 0;
|
|
|
|
const char *type = 0;
|
|
|
|
int off;
|
2007-06-06 09:18:54 +00:00
|
|
|
unsigned size = [aKey length] * 8;
|
2006-02-27 09:35:19 +00:00
|
|
|
char key[size+1];
|
2002-02-25 07:05:58 +00:00
|
|
|
|
2005-03-02 11:46:21 +00:00
|
|
|
GSOnceMLog(@"This method is deprecated, use -setValue:forKey:");
|
2006-02-27 09:35:19 +00:00
|
|
|
[aKey getCString: key
|
|
|
|
maxLength: size+1
|
2007-06-06 09:18:54 +00:00
|
|
|
encoding: NSUTF8StringEncoding];
|
|
|
|
size = strlen(key);
|
2005-03-02 11:46:21 +00:00
|
|
|
if (size > 0)
|
2002-02-25 07:05:58 +00:00
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
char buf[size+6];
|
|
|
|
char lo;
|
|
|
|
char hi;
|
|
|
|
|
|
|
|
strcpy(buf, "_set");
|
2006-02-27 09:35:19 +00:00
|
|
|
strcpy(&buf[4], key);
|
2002-02-25 07:05:58 +00:00
|
|
|
lo = buf[4];
|
|
|
|
hi = islower(lo) ? toupper(lo) : lo;
|
|
|
|
buf[4] = hi;
|
|
|
|
buf[size+4] = ':';
|
2002-02-27 09:01:32 +00:00
|
|
|
buf[size+5] = '\0';
|
2002-02-25 07:05:58 +00:00
|
|
|
|
|
|
|
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;
|
2003-03-27 08:57:14 +00:00
|
|
|
name = &buf[4]; // key
|
2002-11-29 14:21:09 +00:00
|
|
|
if (GSObjCFindVariable(self, name, &type, &size, &off) == NO)
|
2002-02-25 07:05:58 +00:00
|
|
|
{
|
2003-03-27 08:57:14 +00:00
|
|
|
name = &buf[3]; // _key
|
2002-11-29 14:21:09 +00:00
|
|
|
GSObjCFindVariable(self, name, &type, &size, &off);
|
2002-02-25 07:05:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-02-27 09:35:19 +00:00
|
|
|
GSObjCSetVal(self, key, anObject, sel, type, size, off);
|
2002-02-25 07:05:58 +00:00
|
|
|
}
|
|
|
|
|
2004-09-19 23:24:36 +00:00
|
|
|
|
2002-02-25 07:05:58 +00:00
|
|
|
- (void) takeValue: (id)anObject forKeyPath: (NSString*)aKey
|
|
|
|
{
|
|
|
|
NSRange r = [aKey rangeOfString: @"."];
|
|
|
|
|
2005-03-02 11:46:21 +00:00
|
|
|
GSOnceMLog(@"This method is deprecated, use -setValue:forKeyPath:");
|
2002-02-25 07:05:58 +00:00
|
|
|
if (r.length == 0)
|
|
|
|
{
|
|
|
|
[self takeValue: anObject forKey: aKey];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSString *key = [aKey substringToIndex: r.location];
|
|
|
|
NSString *path = [aKey substringFromIndex: NSMaxRange(r)];
|
|
|
|
|
|
|
|
[[self valueForKey: key] takeValue: anObject forKeyPath: path];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-19 23:24:36 +00:00
|
|
|
|
2002-02-25 07:05:58 +00:00
|
|
|
- (void) takeValuesFromDictionary: (NSDictionary*)aDictionary
|
|
|
|
{
|
|
|
|
NSEnumerator *enumerator = [aDictionary keyEnumerator];
|
|
|
|
NSNull *null = [NSNull null];
|
|
|
|
NSString *key;
|
|
|
|
|
2006-04-26 12:24:03 +00:00
|
|
|
GSOnceMLog(@"This method is deprecated, use -setValuesForKeysWithDictionary:");
|
2002-02-25 07:05:58 +00:00
|
|
|
while ((key = [enumerator nextObject]) != nil)
|
|
|
|
{
|
2003-02-19 14:42:07 +00:00
|
|
|
id obj = [aDictionary objectForKey: key];
|
2002-02-25 07:05:58 +00:00
|
|
|
|
|
|
|
if (obj == null)
|
|
|
|
{
|
|
|
|
obj = nil;
|
|
|
|
}
|
|
|
|
[self takeValue: obj forKey: key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-19 23:24:36 +00:00
|
|
|
|
2002-02-25 07:05:58 +00:00
|
|
|
- (void) unableToSetNilForKey: (NSString*)aKey
|
|
|
|
{
|
2005-03-02 11:46:21 +00:00
|
|
|
GSOnceMLog(@"This method is deprecated, use -setNilValueForKey:");
|
2002-02-25 07:05:58 +00:00
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
format: @"%@ -- %@ 0x%x: Given nil value to set for key \"%@\"",
|
|
|
|
NSStringFromSelector(_cmd), NSStringFromClass([self class]), self, aKey];
|
|
|
|
}
|
|
|
|
|
2004-09-19 23:24:36 +00:00
|
|
|
|
2002-02-25 07:05:58 +00:00
|
|
|
- (NSDictionary*) valuesForKeys: (NSArray*)keys
|
|
|
|
{
|
|
|
|
NSMutableDictionary *dict;
|
|
|
|
NSNull *null = [NSNull null];
|
|
|
|
unsigned count = [keys count];
|
|
|
|
unsigned pos;
|
|
|
|
|
2007-11-29 20:56:11 +00:00
|
|
|
GSOnceMLog(@"This method is deprecated, use -dictionaryWithValuesForKeys:");
|
2002-02-25 07:05:58 +00:00
|
|
|
dict = [NSMutableDictionary dictionaryWithCapacity: count];
|
|
|
|
for (pos = 0; pos < count; pos++)
|
|
|
|
{
|
|
|
|
NSString *key = [keys objectAtIndex: pos];
|
|
|
|
id val = [self valueForKey: key];
|
|
|
|
|
|
|
|
if (val == nil)
|
|
|
|
{
|
|
|
|
val = null;
|
|
|
|
}
|
|
|
|
[dict setObject: val forKey: key];
|
|
|
|
}
|
|
|
|
return AUTORELEASE([dict copy]);
|
|
|
|
}
|
|
|
|
|
2007-11-29 20:56:11 +00:00
|
|
|
#endif
|
|
|
|
|
2002-02-25 07:05:58 +00:00
|
|
|
@end
|
|
|
|
|