2012-05-21 5 views
6

未知のクラスのすべてのプロパティとすべてのプロパティのクラスのリストを取得しようとしています。その瞬間、私はオブジェクトのすべてのプロパティのリストを取得します(私はすべてのスーパークラスを取得するために再帰的に行います)。iOS取得プロパティクラス

NSArray* properties = [PropertyUtil classPropsFor:[self class]]; 
for (NSString* property in properties) { 
    id value= [self valueForKey:property]; 
    NSLog(@"Value class for key: %@ is %@", property, [value class]); 
} 

問題は、それがNSStringsためかではなく、カスタムクラスのため、それは私を返すことのために働くです:私は、だから今、私はすべてのプロパティのクラスをしたいと私はthis post

+ (NSArray *)classPropsFor:(Class)klass 
{  
    NSLog(@"Properties for class:%@", klass); 
    if (klass == NULL || klass == [NSObject class]) { 
     return nil; 
    } 

    NSMutableArray *results = [[NSMutableArray alloc] init]; 

    unsigned int outCount, i; 
    objc_property_t *properties = class_copyPropertyList(klass, &outCount); 
    for (i = 0; i < outCount; i++) { 
     objc_property_t property = properties[i]; 
     const char *propName = property_getName(property); 
     if(propName) { 
      NSString *propertyName = [NSString stringWithUTF8String:propName]; 
      [results addObject:propertyName]; 
     } 
     NSArray* dict = [self classPropsFor:[klass superclass]]; 
     [results addObjectsFromArray:dict]; 
    } 
    free(properties); 

    return [NSArray arrayWithArray:results]; 
} 

に触発しましたヌル。私は再帰的に内部に他のオブジェクトを持つことができるオブジェクトを表す辞書を作成したいと思います。私はすべてのプロパティのクラスを知る必要があると思っています。

答えて

2

propertyNameを保存するときに、各プロパティのクラスを(文字列として)保存することをお勧めします。キーとしてのプロパティ名と値としてのクラス名を持つ辞書、またはその逆の辞書である可能性があります。

クラス名を取得するには、このような何か(あなたがpropertyNameを宣言した後に、この権利を置く)を行うことができます。

NSString* propertyAttributes = [NSString stringWithUTF8String:property_getAttributes(property)]; 
NSArray* splitPropertyAttributes = [propertyAttributes componentsSeparatedByString:@"\""]; 
if ([splitPropertyAttributes count] >= 2) 
{ 
    NSLog(@"Class of property: %@", [splitPropertyAttributes objectAtIndex:1]); 
} 

属性は情報の数が含まれているため、コードを扱う文字列があります - 正確な詳細はここに指定されています:https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html

+0

素晴らしい人で完璧です!あなたの助けをありがとう:) – Jpellat

+0

あなたは大歓迎です:) –

2

これはnilである値では動作しません

を更新しました。代わりに、ランタイムC APIを使用して、対応するivarメソッドまたはアクセサメソッドからクラスを取得する必要があります。

+0

プロパティが 'nil'の場合、どのようにクラスが生成されますか? – jlehr

+0

ありがとう!よく無価値を参照してください:) – Jpellat

+0

ようこそ。もう1つ考慮すべきことは、アクセサメソッドを呼び出すと、この時点でトリガしたくない副作用(遅延初期化など)がある可能性があるということです。 – jlehr

7

ちょっとした方法がありました。

// Simple as. 
Class propertyClass = [customObject classOfPropertyNamed:propertyName]; 

多くの方法で最適化できますが、好きです。


実装は次のようになります:

-(Class)classOfPropertyNamed:(NSString*) propertyName 
{ 
    // Get Class of property to be populated. 
    Class propertyClass = nil; 
    objc_property_t property = class_getProperty([self class], [propertyName UTF8String]); 
    NSString *propertyAttributes = [NSString stringWithCString:property_getAttributes(property) encoding:NSUTF8StringEncoding]; 
    NSArray *splitPropertyAttributes = [propertyAttributes componentsSeparatedByString:@","]; 
    if (splitPropertyAttributes.count > 0) 
    { 
     // xcdoc://ios//library/prerelease/ios/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html 
     NSString *encodeType = splitPropertyAttributes[0]; 
     NSArray *splitEncodeType = [encodeType componentsSeparatedByString:@"\""]; 
     NSString *className = splitEncodeType[1]; 
     propertyClass = NSClassFromString(className); 
    } 
    return propertyClass; 
} 

それはNSObject+EPPZRepresentable.hと呼ばれる開発オブジェクトrepresenter内、eppz!kitの一部です。それは、あなたが元来達成しようとしていることを実際に行います。

// Works vica-versa. 
NSDictionary *representation = [customObject dictionaryRepresentation]; 
CustomClass = [CustomClass representableWithDictionaryRepresentation:representation]; 

これは、トラフコレクションを繰り返し、多くの種類をコードCoreGraphicsタイプ、UIColors、また、オブジェクト参照を再構築/表現を表します。


新バージョンが戻ってあなたを吐くも、Cタイプ名と同様という名前の構造体タイプ

NSLog(@"%@", [self typeOfPropertyNamed:@"index"]); // unsigned int 
NSLog(@"%@", [self typeOfPropertyNamed:@"area"]); // CGRect 
NSLog(@"%@", [self typeOfPropertyNamed:@"keyColor"]); // UIColor 

パートeppz!modelの、https://github.com/eppz/eppz.model/blob/master/eppz!model/NSObject%2BEPPZModel_inspecting.m#L111

+3

それは魅力のように動作します! – Kjuly

0

でメソッドの実装を使用して自由に感じます以下は、NSObjectカテゴリに追加されたトリックです。

- (Class) classForKeyPath:(NSString*)keyPath { 
    Class class = 0; 

    unsigned int n = 0; 
    objc_property_t* properties = class_copyPropertyList(self.class, &n); 
    for (unsigned int i=0; i<n; i++) { 
     objc_property_t* property = properties + i; 
     NSString* name = [NSString stringWithCString:property_getName(*property) encoding:NSUTF8StringEncoding]; 
     if (![keyPath isEqualToString:name]) continue; 

     const char* attributes = property_getAttributes(*property); 
     if (attributes[1] == '@') { 
      NSMutableString* className = [NSMutableString new]; 
      for (int j=3; attributes[j] && attributes[j]!='"'; j++) 
       [className appendFormat:@"%c", attributes[j]]; 
      class = NSClassFromString(className); 
     } 
     break; 
    } 
    free(properties); 

    return class; 
} 
関連する問題