Objective-Cでメタプログラミング  プロパティが欲しいの巻

こんにちは ビンゴ中西です。

Objective-Cでクラスのインスタンス変数名を取得したくなりました。

@property(nonatomic, strong) NSString *hoge;

で宣言したところの今回はhogeにあたる部分ですね。
こいつをNSStringの配列で欲しくなったわけであります。

メタプログラミングの代表格はKVC

Objective-Cでのメタプログラミングといったら key value codingだろということで、
KVCについて調べていたのですが、どうもメタプロ的に値はsetできても、
プロパティをgetするものがなさそう...... 困った....

AndroidiPhoneもどっちでもこい! なんでもこなす弊社エンジニアに聞いてみよう!

「プロパティを配列で欲しいんですけどどうしたらよいでしょう?」
「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);