クラス/オブジェクトが持つプロパティ情報を取得するには、Objective-C のランタイムにある、
objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount);
を使用します。
また objc_property_t 型のプロパティ情報からプロパティ名を取得するには、同じくobjcランタイム内の
const char *property_getName(objc_property_t property);
を使用します。
プロパティ名一覧を返すメソッドの実装例
まずランタイムのヘッダをインポート。
#import "objc/runtime.h"
こんな感じでプロパティ名一覧を返すメソッドを実装できます。
- (NSArray *)propertyNames { unsigned int outCount, i; objc_property_t *properties = class_copyPropertyList([self class], &outCount); NSMutableArray *arr = [NSMutableArray arrayWithCapacity:0]; for(i = 0; i < outCount; i++) { objc_property_t property = properties[i]; const char *propName = property_getName(property); if(propName) { NSString *propertyName = [NSString stringWithCString:propName]; [arr addObject:propertyName]; } } free(properties); return arr; }
プロパティ名と型を返すメソッドの実装例
まず、objc_property_t 型のプロパティ情報から型名を取り出すメソッドを実装します。
※こちらのページの2つ目の回答に載っているコードほぼそのまんまです。(1つ目の回答のコードだとエラーになる場合があります)
static const char * getPropertyType(objc_property_t property) { const char *attributes = property_getAttributes(property); char buffer[1 + strlen(attributes)]; strcpy(buffer, attributes); char *state = buffer, *attribute; while ((attribute = strsep(&state, ",")) != NULL) { if (attribute[0] == 'T' && attribute[1] != '@') { return (const char *)[[NSData dataWithBytes:(attribute + 1) length:strlen(attribute) - 1] bytes]; } else if (attribute[0] == 'T' && attribute[1] == '@' && strlen(attribute) == 2) { return "id"; } else if (attribute[0] == 'T' && attribute[1] == '@') { return (const char *)[[NSData dataWithBytes:(attribute + 3) length:strlen(attribute) - 4] bytes]; } } return ""; }
で、下記のように、キーとしてプロパティ名、値として型名を持つ NSDictionary 型でプロパティ一覧を返すメソッドを実装できます。
- (NSDictionary *)properties { unsigned int outCount, i; objc_property_t *props = class_copyPropertyList([self class], &outCount); NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:0]; for(i = 0; i < outCount; i++) { objc_property_t property = props[i]; const char *propName = property_getName(property); if(propName) { const char *propType = getPropertyType(property); NSString *propertyName = [NSString stringWithCString:propName]; NSString *propertyType = [NSString stringWithCString:propType]; [dic setObject:propertyType forKey:propertyName]; } } free(props); return dic; }