My naïve solution is as follows:
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [[self class] instanceMethodSignatureForSelector:@selector(foo:)];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
NSString *argument;
[anInvocation getArgument:&argument atIndex:2];
if (argument) {
NSString *setterName = NSStringFromSelector(anInvocation.selector);
NSRange range = NSMakeRange(3, [setterName length]-4);
NSString *propertyName = [[setterName substringWithRange:range] lowercaseString];
[self performSelector:@selector(setFoo:value:) withObject:propertyName withObject:argument];
} else {
[self performSelector:@selector(foo:) withObject:argument];
}
}
- (id)foo:(id)key
{
return self.properties[key];
}
- (void)setFoo:(id)key value:(id)value
{
self.properties[key] = value;
}
- (id)valueForKey:(NSString *)key
{
return self.properties[key];
}
- (void)setValue:(id)value forKey:(NSString *)key
{
self.properties[key] = value;
}
I will update with a cleaner version later as I optimize for value types and the such.