オブジェクトのすべてのプロパティをループし、 "名前"と "値"を取得する方法はありますか?Objective- C - クラス内のすべてのプロパティをループしますか?
オブジェクトをプロパティ名と値に基づいて文字列にシリアル化するカテゴリを作成しようとしています。私は、各クラスのエンコーディングメソッドを記述しないで、代わりに汎用クラスを記述しようとしています。
これは可能ですか?
オブジェクトのすべてのプロパティをループし、 "名前"と "値"を取得する方法はありますか?Objective- C - クラス内のすべてのプロパティをループしますか?
オブジェクトをプロパティ名と値に基づいて文字列にシリアル化するカテゴリを作成しようとしています。私は、各クラスのエンコーディングメソッドを記述しないで、代わりに汎用クラスを記述しようとしています。
これは可能ですか?
このコードを使用して、クラス内で宣言されているすべてのプロパティとプロパティのすべての属性を列挙できます。私はあなたがより多くのタイプ属性を解析することに興味があると思います。詳細は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);
多分class_copyPropertyList()
は、あなたが何をしているかを行いますが、宣言されたプロパティのみを返すことに注意してください。
すべてのプロパティが宣言されているわけではありません - NSDictionary
およびNSMutableDictionary
は、クラスで宣言されていないプロパティを設定できるクラスの例です。
詳細はdocsです。
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
ああ神よ、これはとても汚いと感じています... – buildsucceeded
initWithCStringは廃止され、[[NSString alloc] initWithBytes:property_getName(property)length:strlen(property_getName(property))encoding:NSUTF8StringEncoding]が代わりに機能します。 –
'property_getName'の戻り値は自由でなければなりませんか? –
コメントはまだありませんが、@ 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
魅力的なアイデアですが、その道のりは狂気です。あなたは車輪を再発明するでしょう(Core Dataはすでに優れたモデルベースの永続性を提供しています)。また、プロパティシステムはあらゆる種類の自動永続性の基礎となるようには設計されていません。最終結果は恐ろしく壊れやすく、Cデータタイプのばらつきを考えると、最初の書き込みには完全な苦痛があります。 – bbum
私のupvoteにもかかわらず、以下の "プロパティは"答えてください...これはあなたがコアデータを学ぶ必要があるときです。真剣に、それはそれの価値があるでしょう。初心者のためではなく、いったんobjcランタイムをハッキングするようなことをやってみると、それらの奇妙なドキュメントを読んで、あなたの頭の中を正しい方法でやるようになるでしょう。 :) – buildsucceeded
@buildsucceeded私はコアデータの使い方を知っています。それは、リレーショナルデータを必要とする中規模/大規模プロジェクトには最適なソリューションです。しかし、アプリケーションの状態を維持するために単一のオブジェクトをシリアル化する必要がある非常に小さなプロジェクトでは、コアデータを使用するのが面倒です。さらに、Object-To-Dictionary-SerializationやDI Frameworkなどの目的でこのソリューションを使用しました。 – aryaxt