如何在NSObject实例中为我的自定义键(undefinedKey)设置一个值?

时间:2011-02-16 09:05:15

标签: iphone objective-c

我已经将NSObject子类化了。我需要将一个对象(NSMutableArray实例)设置为该类实例的未定义​​键(@"ItemsList")。我怎样才能做到这一点?例如,我想设置,

[myObject setValue:myArray forUndefinedKey:@"ItemsList"];

我应该做些什么来使这项工作?

3 个答案:

答案 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"];