我已经将NSObject子类化了。我需要将一个对象(NSMutableArray
实例)设置为该类实例的未定义键(@"ItemsList"
)。我怎样才能做到这一点?例如,我想设置,
[myObject setValue:myArray forUndefinedKey:@"ItemsList"];
我应该做些什么来使这项工作?
答案 0 :(得分:3)
这是一种轻松实现这一目标的方法,无需创建ivars:
@interface MONObject : NSObject
{
NSMutableDictionary * stuff;
}
// ....
- (void)setValue:(id)value forCustomKey:(NSString *)key;
@end
@implementation MONObject
- (void)setValue:(id)value forCustomKey:(NSString *)key
{
assert(self.stuff && value && key);
[self.stuff setValue:value forKey:key];
}
@end
答案 1 :(得分:2)
您可以使用这样的类,并将其子类化。 (参见下面的子类,并注意如何 testProperty未合成,但用作动态)
@interface INDynamicPersister : NSObject {
}
/*!
@method saveObject:forKey:
@abstract Invoked when a property setter is invoked.
*/
- (void) saveObject:(id)value forKey:(NSString *)key;
/*!
@method retrieveObjectForKey:
@abstract Invoked when a property getter needs its value.
*/
- (id) retrieveObjectForKey:(NSString *)key;
@end
#define Property_Setter_Suffix @":"
@implementation INDynamicPersister
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
NSMethodSignature *signature = [super methodSignatureForSelector:sel];
if ( signature == nil ) {
// get the name of the selector
NSString *selectorName = [NSStringFromSelector(sel) lowercaseString];
// if we have a setter property ...
if ( [selectorName hasSuffix:Property_Setter_Suffix] ) {
signature = [NSMethodSignature signatureWithObjCTypes:"v@:@"];
}
else {
signature = [NSMethodSignature signatureWithObjCTypes:"@@:"];
}
}
return signature;
}
/*!
@method forwardInvocation:
@abstract This method will handle the invocation for the property getters and setters.
*/
- (void)forwardInvocation:(NSInvocation *)anInvocation {
// get the name of the selector
NSString *selectorName = [NSStringFromSelector([anInvocation selector]) lowercaseString];
// if we have a setter property ...
if ( [selectorName hasSuffix:Property_Setter_Suffix] ) {
int selectorLength = [selectorName length];
NSString *propertyName = [selectorName substringWithRange:NSMakeRange(3, selectorLength - 4)];
// get the value of the invocation
id invocationValue;
[anInvocation getArgument:&invocationValue atIndex:2];
// now set the value for the property
[self saveObject:invocationValue forKey:propertyName];
}
else {
// if we have a getter property ...
id invocationReturnValue = [self retrieveObjectForKey:selectorName];
[anInvocation setReturnValue:&invocationReturnValue];
}
}
- (void) saveObject:(id)value forKey:(NSString *)key {
[NSException raise:@"NotImplementedException" format:@"You need to override this method"];
}
- (id) retrieveObjectForKey:(NSString *)key {
[NSException raise:@"NotImplementedException" format:@"You need to override this method"];
return nil; // compiler is happy now
}
@end
子类可能与此类似:
@interface MyDynamicEntity : INDynamicPersister {
NSMutableDictionary *propertyValues;
}
@property (retain, nonatomic) NSString * testProperty;
@end
@implementation MyDynamicEntity
@dynamic testProperty;
- (id) init {
if ( self = [super init] ) {
propertyValues = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void) dealloc {
[propertyValues release], propertyValues = nil;
[super dealloc];
}
- (void) saveObject:(id)value forKey:(NSString *)key {
if ( !value ) {
[propertyValues removeObjectForKey:key];
}
else {
[propertyValues setObject:value forKey:key];
}
}
- (id) retrieveObjectForKey:(NSString *)key {
return [propertyValues objectForKey:key];
}
@end
希望这会有所帮助:)
答案 2 :(得分:0)
@interface MyObject : NSObject
@end
@implementation MyObject {
NSMutableDictionary*itemsList;
}
- (id)valueForUndefinedKey:(NSString*)key {
if ([key isEqualToString:@"itemsList"]) {
return itemsList;
}
else {
return [super valueForUndefinedKey:key];
}
}
- (void)setValue:(id)value forUndefinedKey:(NSString*)key {
if ([key isEqualToString:@"itemsList"]) {
itemsList = value;
}
else {
[super setValue:value forUndefinedKey:key];
}
}
@end
对于调用属性,需要通过valueForKey调用它:
MyObject*myObject = [MyObject new];
[myObject setValue:@[@"item1", @"item2"] forKey:@"itemsList"];
NSArray*itemsList = [myObject valueForKey:@"itemsList"];