2012-02-12 16 views
16

オブジェクトのすべてのプロパティをループし、 "名前"と "値"を取得する方法はありますか?Objective- C - クラス内のすべてのプロパティをループしますか?

オブジェクトをプロパティ名と値に基づいて文字列にシリアル化するカテゴリを作成しようとしています。私は、各クラスのエンコーディングメソッドを記述しないで、代わりに汎用クラスを記述しようとしています。

これは可能ですか?

+3

魅力的なアイデアですが、その道のりは狂気です。あなたは車輪を再発明するでしょう(Core Dataはすでに優れたモデルベースの永続性を提供しています)。また、プロパティシステムはあらゆる種類の自動永続性の基礎となるようには設計されていません。最終結果は恐ろしく壊れやすく、Cデータタイプのばらつきを考えると、最初の書き込みには完全な苦痛があります。 – bbum

+0

私のupvoteにもかかわらず、以下の "プロパティは"答えてください...これはあなたがコアデータを学ぶ必要があるときです。真剣に、それはそれの価値があるでしょう。初心者のためではなく、いったんobjcランタイムをハッキングするようなことをやってみると、それらの奇妙なドキュメントを読んで、あなたの頭の中を正しい方法でやるようになるでしょう。 :) – buildsucceeded

+0

@buildsucceeded私はコアデータの使い方を知っています。それは、リレーショナルデータを必要とする中規模/大規模プロジェクトには最適なソリューションです。しかし、アプリケーションの状態を維持するために単一のオブジェクトをシリアル化する必要がある非常に小さなプロジェクトでは、コアデータを使用するのが面倒です。さらに、Object-To-Dictionary-SerializationやDI Frameworkなどの目的でこのソリューションを使用しました。 – aryaxt

答えて

21

このコードを使用して、クラス内で宣言されているすべてのプロパティとプロパティのすべての属性を列挙できます。私はあなたがより多くのタイプ属性を解析することに興味があると思います。詳細はhereです。

unsigned int numOfProperties; 
objc_property_t *properties = class_copyPropertyList([self class], &numOfProperties); 
for (unsigned int pi = 0; pi < numOfProperties; pi++) { 
    // Examine the property attributes 
    unsigned int numOfAttributes; 
    objc_property_attribute_t *propertyAttributes = property_copyAttributeList(properties[pi], &numOfAttributes); 
    for (unsigned int ai = 0; ai < numOfAttributes; ai++) { 
     switch (propertyAttributes[ai].name[0]) { 
      case 'T': // type 
       break; 
      case 'R': // readonly 
       break; 
      case 'C': // copy 
       break; 
      case '&': // retain 
       break; 
      case 'N': // nonatomic 
       break; 
      case 'G': // custom getter 
       break; 
      case 'S': // custom setter 
       break; 
      case 'D': // dynamic 
       break; 
      default: 
       break; 
     } 
    } 
    free(propertyAttributes); 
} 
free(properties); 
+1

さまざまな名前の賢明な定義が理由で公開されていないことに注意してください。これは、今後変更される可能性のある実装の詳細です。 – bbum

+0

@bbum合意しましたが、公開された情報は、実行時に動的プロパティのアクセサメソッドを生成するのに十分役立ちます。 – Costique

+0

@Costiqueアトリビュート配列内のすべての属性の.name、.valueを解放するのはどうですか?誰が所有者、ランタイム、または開発者を所有していますか? – Andy

1

多分class_copyPropertyList()は、あなたが何をしているかを行いますが、宣言されたプロパティのみを返すことに注意してください。

すべてのプロパティが宣言されているわけではありません - NSDictionaryおよびNSMutableDictionaryは、クラスで宣言されていないプロパティを設定できるクラスの例です。

詳細はdocsです。

2
私はログエントリで、その結果、 NSLog(@"%@", [someObject propertiesPlease]);、例えば、言うこと NSObjectに次のカテゴリを使用し

のような...

someObject: { 
    color = "NSCalibratedRGBColorSpace 0 0 1 1"; 
    crayon = Blueberry; 
} 

NSObjectの+ Additions.h

@interface NSObject (Additions) 
- (NSDictionary *)propertiesPlease; 
@end 

NSObject + Additions.m

@implementation NSObject (Additions) 
- (NSDictionary *)propertiesPlease { 
NSMutableDictionary *props = [NSMutableDictionary dictionary]; 
unsigned int outCount, i; 
objc_property_t *properties = class_copyPropertyList([self class], &outCount); 
for (i = 0; i < outCount; i++) { 
    objc_property_t property = properties[i]; 
    NSString *propertyName = [[NSString alloc] initWithCString:property_getName(property)]; 
    id propertyValue = [self valueForKey:(NSString *)propertyName]; 
    if (propertyValue) [props setObject:propertyValue forKey:propertyName]; 
} 
    free(properties); 
    return props; 
} 
@end 
+1

ああ神よ、これはとても汚いと感じています... – buildsucceeded

+1

initWithCStringは廃止され、[[NSString alloc] initWithBytes:property_getName(property)length:strlen(property_getName(property))encoding:NSUTF8StringEncoding]が代わりに機能します。 –

+0

'property_getName'の戻り値は自由でなければなりませんか? –

0

コメントはまだありませんが、@ Costiqueの回答に追加するには、プロパティ値がバインドされる可能性のあるIVarの名前であるタイプ値 "V"(synthesisize )。このことは、容易に編集済みこの

@interfaceで発見することができます:NSObjectの

@property(原子、読み取り専用)のint fooという。

@end


@implementation編集さ

@synthesize FOO = fooBarに。

@end

// for all properties 
unsigned propertyCount = 0; 
objc_property_t *properties = class_copyPropertyList([object class], &propertyCount); 
for (int prop = 0; prop < propertyCount; prop++) 
{ 
    // for all property attributes 
    unsigned int attributeCount = 0; 
    objc_property_attribute_t* attributes = property_copyAttributeList(property, &attributeCount); 
    for (unsigned int attr = 0; attr < attributeCount; attr++) 
    { 
     NSLog(@"Attribute %d: name: %s, value: %s", attr, attributes[attr].name, attributes[attr].value); 
    } 
} 

2013年7月8日13:47:16.600 Redacted5162:303]項目0:名前:T、値:I

2013年7月8日13 :47:16.601 Redacted [5162:303]項目1:名前:R、値:

2013-07-08 13:47:16602 Redacted [5162:303]属性2:名前:V、値:fooBar

関連する問題