2009-04-20 12 views
19

में एक संपत्ति रिटर्न प्रकार का पता लगाने के लिए कैसे मेरे पास रनटाइम पर उद्देश्य-सी में एक ऑब्जेक्ट है, जिसमें से मुझे केवल केवीसी कुंजी पता है और मुझे वापसी मूल्य प्रकार का पता लगाने की आवश्यकता है (उदाहरण के लिए मुझे यह जानने की ज़रूरत है कि क्या एक एनएसएआरएआरई या एनएसएमयूटेबलएरे) इस संपत्ति के, मैं यह कैसे कर सकता हूं?उद्देश्य-सी

+0

कहाँ जानकारी करता है आपकी एक्सएमएल फाइल में से आते हैं? क्या प्रत्येक संपत्ति के प्रकार को इंगित करने के लिए एक प्रविष्टि जोड़ना संभव होगा? –

+0

एक्सएमएल फ़ाइल भी मेरे नियंत्रण से बाहर है। मैं एक एक्सएमएल सीरिएलाइज़र बना रहा हूं जो एक ऑब्जेक्ट संरचना में एक एक्सएमएल फ़ाइल को परिवर्तित करता है। बेशक, ऑब्जेक्ट्स उपलब्ध होना चाहिए, लेकिन डेटा को सही तरीके से भरने के लिए मुझे रनटाइम पर ऑब्जेक्ट के बारे में निश्चित जानकारी चाहिए। – Enyra

उत्तर

34

आप रनटाइम संपत्ति आत्मनिरीक्षण के बारे में बात कर रहे हैं, जो कुछ ऐसा होता है जो उद्देश्य-सी very good at है।

@interface MyClass 
{ 
    NSArray * stuff; 
} 
@property (retain) NSArray * stuff; 
@end 

कौन इस तरह एक्सएमएल कुछ में encoded हो जाता है:

मामले आपके द्वारा बताई में, मैं आप इस तरह एक वर्ग है यह सोचते कर रहा हूँ इस जानकारी से

<class> 
    <name>MyClass</name> 
    <key>stuff</key> 
</class> 

, आप चाहते हैं कक्षा को फिर से बनाने के लिए और इसे stuff के लिए उपयुक्त मान भी दें।

यहाँ यह कैसे दिखाई दे सकती है:

#import <objc/runtime.h> 

// ... 

Class objectClass;  // read from XML (equal to MyClass) 
NSString * accessorKey; // read from XML (equals @"stuff") 

objc_property_t theProperty = 
    class_getProperty(objectClass, accessorKey.UTF8String); 

const char * propertyAttrs = property_getAttributes(theProperty); 
// at this point, propertyAttrs is equal to: [email protected]"NSArray",&,Vstuff 
// thanks to Jason Coco for providing the correct string 

// ... code to assign the property based on this information 

एप्पल के प्रलेखन (ऊपर लिंक) आप propertyAttrs में देखने की उम्मीद कर सकते हैं कि क्या के बारे में गंदा विवरण के सभी है।

+2

असल में, यह टी @ "एनएसएआरएआरई" के बराबर होगा, और, Vstuff ;-) –

+0

धन्यवाद, आप बिल्कुल सही हैं। मैंने परिवर्तन किया है –

+0

धन्यवाद, यह सबसे अच्छा तरीका प्रतीत होता है, मैं इसे आजमा रहा हूं। बीटीडब्ल्यू। आपका उदाहरण काफी कुछ है जो मैं कर रहा हूं, लेकिन यह कोई एक्सएमएल फ़ाइल हो सकता है, इसलिए मेरी कुंजी तत्व का नाम है। – Enyra

1

आप उपयोग कर सकते हैं isKindOfClass संदेश

if([something isKindOfClass:NSArray.class]) 
    [somethingElse action]; 
+1

समस्या यह है कि ऑब्जेक्ट नव निर्मित है, इसलिए संपत्ति मूल्य शून्य है। मेरे पास सिर्फ एक केवीसी कुंजी है, जिसमें से मुझे पता नहीं है कि ऑब्जेक्ट में वास्तव में यह एक्सेसर्स है या नहीं, लेकिन यदि यह है, तो मुझे इस ऑब्जेक्ट को हाथ में दिए बिना इस वापसी मूल्य के प्रकार को जानने की आवश्यकता है। – Enyra

+0

जब आपके पास ऑब्जेक्ट होगा तो बाद में अपना तर्क निर्णय क्यों न लें? उद्देश्य सी अधिक रनटाइम भाषा तब स्थिर है। –

+0

@Enyra: यह ठीक है। उपर्युक्त का उपयोग करना, यदि ऑब्जेक्ट शून्य है, तो यह अंततः एक सरणी होने के बावजूद झूठी वापसी करेगा। –

4

पसंदीदा तरीका तरीकों NSObject Protocol में परिभाषित का प्रयोग है।

विशेष रूप से, यह निर्धारित करने के लिए कि क्या कक्षा या उस वर्ग के उप-वर्ग का उदाहरण है, तो आप -isKindOfClass: का उपयोग करते हैं। अगर कुछ एक विशेष वर्ग का एक उदाहरण है, और केवल उस वर्ग है निर्धारित करने के लिए (यानी: नहीं एक उपवर्ग), -isMemberOfClass:

तो उपयोग करते हैं, अपने मामले के लिए, अगर आप इस तरह कुछ करना चाहता हूँ चाहते हैं:

// Using -isKindOfClass since NSMutableArray subclasses should probably 
// be handled by the NSMutableArray code, not the NSArray code 
if ([anObject isKindOfClass:NSMutableArray.class]) { 
    // Stuff for NSMutableArray here 
} else if ([anObject isKindOfClass:NSArray.class]) { 
    // Stuff for NSArray here 

    // If you know for certain that anObject can only be 
    // an NSArray or NSMutableArray, you could of course 
    // just make this an else statement. 
} 
+2

एनियारा मामले में 'anObject' शून्य है। मेरे जवाब में टिप्पणियां देखें। –

+1

यह परीक्षण काम नहीं करेगा। सभी सरणी - यहां तक ​​कि अपरिवर्तनीय वाले - एनएसएमयूटेबलएरे से निकले हैं। – Chuck

+2

isMemberOfClass: वह चेक है जो विरासत को अनदेखा करता है। –

17

सस्ता उत्तर: the NSObject+Properties source here का उपयोग करें।

यह ऊपर वर्णित वही पद्धति लागू करता है।

+1

महान lib के लिए +1 :) – Kjuly

+0

मैं अक्सर पहिया को फिर से शुरू करना चाहता हूं, इसलिए शायद मैं ऐसा कुछ करूंगा और इस लाइब्रेरी का उदाहरण/संदर्भ के रूप में उपयोग करूंगा। आपको बहुत - बहुत धन्यवाद! –

2

यह वास्तव में ई-जेम्स 21APR09 द्वारा प्रदान किए गए उत्तर के जवाब में ग्रेग मैलेटिक द्वारा उठाए गए एक मुद्दे को संबोधित करने वाली एक टिप्पणी है।

सहमत हैं कि उद्देश्य-सी इन विशेषताओं को प्राप्त करने के लिए बेहतर कार्यान्वयन का उपयोग कर सकता है।विशेषता चाबियों का

- (NSArray*) attributesOfProp:(NSString*)propName ofObj:(id)obj{ 

    objc_property_t prop = class_getProperty(obj.class, propName.UTF8String); 
    if (!prop) { 
     // doesn't exist for object 
     return nil; 
    } 
    const char * propAttr = property_getAttributes(prop); 
    NSString *propString = [NSString stringWithUTF8String:propAttr]; 
    NSArray *attrArray = [propString componentsSeparatedByString:@","]; 
    return attrArray; 
} 

आंशिक सूची:

  • आर केवल-पढ़ने के
  • सी अंतिम मान की कॉपी सौंपा नीचे एक विधि मैं जल्दी से एक साथ फेंक दिया एक वस्तु संपत्ति की विशेषताओं को पुनः प्राप्त करने के लिए है
  • & अंतिम मान सौंपा
  • एन nonatomic संपत्ति के संदर्भ
  • डब्ल्यू कमजोर संदर्भ

Apple

+1

ब्रैप मैसेजिंग से डॉट-सिंटैक्स तक स्लिप डी। थॉम्पसन के संपादन के बारे में नोट: उपरोक्त डॉट-सिंटैक्स संपादन वास्तव में एक्सकोड 6.4 और एक्सकोड 7 बीटा ("आप दोनों में" obj.class "कॉल के लिए एक कंपाइलर त्रुटि में परिणाम देगा हल करने के लिए "एनएसओब्जेक्ट" को "आईडी" घोषणा को अपडेट करने की आवश्यकता है)। मैं जॉन रीड की राय का समर्थक हूं कि ओबीजेसी में मैसेजिंग के लिए डॉट-सिंटैक्स का उपयोग आम तौर पर मूर्खतापूर्ण है: http://qualitycoding.org/dot-notation/#comments – Jalakoo

0

पर पूर्ण सूची आप जानते हैं कि संपत्ति परिभाषित किया गया है:

 id vfk = [object valueForKey:propertyName]; 
     Class vfkClass = vfk.class; 

और isKindOfClass, isSubClass के साथ तुलना करें, आदि

+1

क्या होगा यदि वर्तमान मान शून्य है? – JBlake