You can use a class like this and subclass it. (see the subclass below and note how testProperty is not synthesized, but used as dynamic)
@interface INDynamicPersister : NSObject {
}
- (void) saveObject:(id)value forKey:(NSString *)key;
- (id) retrieveObjectForKey:(NSString *)key;
@end
#define Property_Setter_Suffix @":"
@implementation INDynamicPersister
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
NSMethodSignature *signature = [super methodSignatureForSelector:sel];
if ( signature == nil ) {
NSString *selectorName = [NSStringFromSelector(sel) lowercaseString];
if ( [selectorName hasSuffix:Property_Setter_Suffix] ) {
signature = [NSMethodSignature signatureWithObjCTypes:"v@:@"];
}
else {
signature = [NSMethodSignature signatureWithObjCTypes:"@@:"];
}
}
return signature;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
NSString *selectorName = [NSStringFromSelector([anInvocation selector]) lowercaseString];
if ( [selectorName hasSuffix:Property_Setter_Suffix] ) {
int selectorLength = [selectorName length];
NSString *propertyName = [selectorName substringWithRange:NSMakeRange(3, selectorLength - 4)];
id invocationValue;
[anInvocation getArgument:&invocationValue atIndex:2];
[self saveObject:invocationValue forKey:propertyName];
}
else {
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;
}
@end
A subclass might be something like this:
@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
Hope this helps :)