Objective-Cでメタプログラミング プロパティが欲しいの巻
こんにちは ビンゴ中西です。
Objective-Cでクラスのインスタンス変数名を取得したくなりました。
@property(nonatomic, strong) NSString *hoge;
で宣言したところの今回はhogeにあたる部分ですね。
こいつをNSStringの配列で欲しくなったわけであります。
メタプログラミングの代表格はKVC
Objective-Cでのメタプログラミングといったら key value codingだろということで、
KVCについて調べていたのですが、どうもメタプロ的に値はsetできても、
プロパティをgetするものがなさそう...... 困った....
AndroidもiPhoneもどっちでもこい! なんでもこなす弊社エンジニアに聞いてみよう!
「プロパティを配列で欲しいんですけどどうしたらよいでしょう?」
「Classクラスみたいなのがあるんじゃなかったっけ?」
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html
「class_copyPropertyListじゃない?」
「おお! これだ!」
class_copyPropertyListや! class_copyPropertyListを使うんや!
ということで書いたソースがこちら
配列でGET
#import <Foundation/NSObjCRuntime.h> #import <objc/runtime.h> +(NSMutableArray *)getProperties:(id)c { NSString *propertyName; unsigned int outCount, i; NSMutableArray *propertieNames = [[NSMutableArray alloc] initWithObjects: nil]; objc_property_t *properties = class_copyPropertyList(c, &outCount); for (i = 0; i < outCount; i++) { objc_property_t property = properties[i]; propertyName = [NSString stringWithUTF8String:property_getName(property)]; [propertieNames addObject:propertyName]; } return propertieNames; }
使い方
NSMutableArray *a = [self getProperties:[Hoge class]]; for (id i in a) { NSLog(@"P : %@", i); }
ディクショナリでGET
こっちはKVCも使ってます:)
+(NSMutableDictionary *)getPropertiesDictionary:(id)o { NSString *propertyName; unsigned int outCount, i; NSMutableDictionary *propertieDictionary = [[NSMutableDictionary alloc] initWithObjectsAndKeys: nil]; objc_property_t *properties = class_copyPropertyList([o class], &outCount); for (i = 0; i < outCount; i++) { objc_property_t property = properties[i]; propertyName = [NSString stringWithUTF8String:property_getName(property)]; [propertieDictionary setObject:[o valueForKey:propertyName] forKey:propertyName]; } return propertieDictionary; }
使い方
NSMutableDictionary *d = [self getPropertiesDictionary:foo]; // インスタンスをあげる NSLog(@"D : %@", d);