2012-05-21 10 views
6

मिलता है मैं एक अज्ञात वर्ग और प्रत्येक संपत्ति के वर्ग की सभी संपत्तियों की एक सूची प्राप्त करने की कोशिश कर रहा हूं। इस समय तक मुझे किसी ऑब्जेक्ट के सभी गुणों की एक सूची मिलती है (मैं इसे सभी सुपरक्लास प्राप्त करने के लिए बार-बार करता हूं)। मैं 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]; 
} 

में प्रेरित तो अब मैं हर संपत्ति के वर्ग चाहता हूँ और मैं कार्य करें:

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 या के लिए काम करता है लेकिन कस्टम कक्षाओं के लिए नहीं है कि यह मुझे देता है के लिए, है शून्य। मैं एक ऐसे शब्दकोश को फिर से बनाना चाहता हूं जो किसी ऑब्जेक्ट का प्रतिनिधित्व करता हो जिसमें अन्य वस्तुओं को अंदर रखा जा सके और जैसा कि मुझे लगता है कि मुझे हर संपत्ति की कक्षा जानने की आवश्यकता है, क्या यह संभव है?

उत्तर

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

UPDATED

यह मान जो nil रहे हैं के लिए काम नहीं करता। इसके बजाय आपको संबंधित आईवर या एक्सेसर विधि से कक्षा प्राप्त करने के लिए रनटाइम सी एपीआई का उपयोग करना चाहिए।

+0

यदि संपत्ति 'शून्य 'है, तो यह कक्षा कैसे प्राप्त करेगी? – jlehr

+0

धन्यवाद! अच्छी तरह से शून्य मूल्यों के लिए देखें :) – Jpellat

+0

आपका स्वागत है। एक और विचार यह है कि एक्सेसर विधियों का आह्वान करने के दुष्प्रभाव हो सकते हैं - उदाहरण के लिए, आलसी प्रारंभिकरण - कि आप इस बिंदु पर ट्रिगर नहीं करना चाहेंगे। – 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; 
} 

यह eppz!kit का हिस्सा है, के भीतर एक विकासशील वस्तु representer NSObject+EPPZRepresentable.h कहा जाता है। यह वास्तव में वह करता है जो आप मूल रूप से हासिल करना चाहते हैं।

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

यह कई प्रकार के पुनरावृति गर्त संग्रह, encodes CoreGraphics प्रकार, UIColors का प्रतिनिधित्व करता है, यह भी प्रतिनिधित्व करते हैं/वस्तु के संदर्भ को फिर से संगठित।


नया संस्करण तुम वापस थूक भी सी प्रकार के नाम और नामित struct प्रकार रूप में अच्छी तरह:

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

भाग, https://github.com/eppz/eppz.model/blob/master/eppz!model/NSObject%2BEPPZModel_inspecting.m#L111

+3

यह एक आकर्षण की तरह काम करता है! – Kjuly

0

पर विधि कार्यान्वयन का उपयोग करने के लिए स्वतंत्र महसूस निम्नलिखित एनएसओब्जेक्ट श्रेणी में जोड़ा गया चाल है।

- (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; 
} 
संबंधित मुद्दे