これを行うには少なくとも2つの方法があります。
使用
objectForKeyedSubscript:
を添字
とsetObject:forKeyedSubscript:
@property (nonatomic,strong) NSMutableDictionary *properties;
- (id)objectForKeyedSubscript:(id)key {
return [[self properties] valueForKey:[NSString stringWithFormat:@"%@",key]];
}
- (void)setObject:(id)object forKeyedSubscript:(id <NSCopying>)key {
[[self properties] setValue:object forKey:[NSString stringWithFormat:@"%@",key]];
}
Person *p = [Person new];
p[@"name"] = @"Jon";
NSLog(@"%@",p[@"name"]);
resolveInstanceMethod:
これは、すべてのメソッドのためのランタイムで実行されるobjc_sendMsgです:
下部を見ると、resolveInstanceMethod:
にアクセスすることができます。これにより、メソッド呼び出しを選択したものにリダイレクトできます。
// generic getter
static id propertyIMP(id self, SEL _cmd) {
return [[self properties] valueForKey:NSStringFromSelector(_cmd)];
}
// generic setter
static void setPropertyIMP(id self, SEL _cmd, id aValue) {
id value = [aValue copy];
NSMutableString *key = [NSStringFromSelector(_cmd) mutableCopy];
// delete "set" and ":" and lowercase first letter
[key deleteCharactersInRange:NSMakeRange(0, 3)];
[key deleteCharactersInRange:NSMakeRange([key length] - 1, 1)];
NSString *firstChar = [key substringToIndex:1];
[key replaceCharactersInRange:NSMakeRange(0, 1) withString:[firstChar lowercaseString]];
[[self properties] setValue:value forKey:key];
}
そしてクラスに要求されたメソッドを追加するresolveInstanceMethod:
を実装します。あなたの質問に答えるために、あなたは見えアップ値を辞書IVARに、一般的なゲッターとセッターを記述する必要があります。
+ (BOOL)resolveInstanceMethod:(SEL)aSEL {
if ([NSStringFromSelector(aSEL) hasPrefix:@"set"]) {
class_addMethod([self class], aSEL, (IMP)setPropertyIMP, "[email protected]:@");
} else {
class_addMethod([self class], aSEL,(IMP)propertyIMP, "@@:");
}
return YES;
}
はまた、それは、NSInvocationで包み、forwardInvocation:
に渡される方法、ためNSMethodSignatureを返しますが、メソッドを追加すると、より高速である可能性があります。
Here is a gist CodeRunnerで実行されます。 myClass["anyProperty"]
コールは処理されません。
はい、可能です。 –
(3つの基本的なメカニズムがあります:1)実際にクラスにメソッドを追加する、2) "認識されないメッセージ"エラーを傍受して実装を提供する、3)プロパティに対してセッターとゲッターを傍受する特定の方法があります。しかし、私は手元に細部を持っていません。) –