2012-04-06 23 views
7

मैं एनएसएलओजी() जैसे किसी फ़ंक्शन या निर्देश लिखना चाहता हूं जो कि किसी प्रकार का चर, प्राइमेटिव और ऑब्जेक्ट लेता है। उस समारोह में मैं उनको अलग करना चाहता हूं।उद्देश्य-सी: यह जांचने के लिए कि कोई चर एक ऑब्जेक्ट है, एक स्ट्रक्चर या अन्य आदिम

मुझे पता है कि यह वस्तुओं के लिए काम करता है:

- (void)test:(id)object { 
    if ([object isKindOfClass:[NSString class]]) 
     ... 

लेकिन मैं structs या यहाँ तक कि पूर्णांक या तैरता से वस्तुओं कैसे भेद है। कुछ ऐसा:

"isKindOfStruct:CGRect" or "isInt" 

उदाहरण के लिए?

क्या यह संभव है? मैंने सोचा था कि आप सब कुछ NSLog (@ "...", ऑब्जेक्ट्स, इन्ट्स, structs) को भेज सकते हैं? यह संभव होना चाहिए?

किसी भी मदद के लिए धन्यवाद!

संपादित

मेरे अंतिम लक्ष्य बहुरूपता किसी तरह लागू करने के लिए है।

मैं अपने समारोह कॉल करने के लिए सक्षम होना चाहते हैं:

MY_FUNCTION(int) 
MY_FUNCTION(CGRect) 
MY_FUNCTION(NSString *) 
... 

or [self MYFUNCTION:int]... 

और MY_FUNCTION में

-(void)MYFUNCTION:(???)value { 
    if ([value isKindOf:int]) 
     ... 
    else if ([value isKindOf:CGRect]) 
     ... 
    else if ([value isKindOfClass:[NSString class]]) 
     ... 
} 

मुझे पता है कि isKindOf मौजूद नहीं है और तुम भी पुरातन पर ऐसी विधियों प्रदर्शन नहीं कर सकते । मैं भी "???" के बारे में निश्चित नहीं हूँ फ़ंक्शन हेडर में सामान्य "प्रकार" का सामान्य प्रकार।

क्या यह संभव है?

+0

Type Encodings at Apple के बारे में अधिक isKindOf मौजूद है। isKindOfClass जांचता है कि कोई वर्ग सदस्य या सबक्लास है, और क्या MemberOfClass जांचता है कि कोई कक्षा * बिल्कुल * एक प्रकार का वर्ग है या नहीं। https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html –

उत्तर

3

NSLog() जैसे फ़ंक्शन बता सकते हैं कि प्रारूप पैरामीटर से आपके पैरामीटर सूची में किस प्रकार की अपेक्षा की जा सकती है जिसे आप पहले पैरामीटर के रूप में पास करते हैं। तो आप इसके प्रकार को समझने के लिए पैरामीटर से क्वेरी नहीं करते हैं - आप प्रारूप स्ट्रिंग के आधार पर आप किस प्रकार की अपेक्षा करते हैं, और फिर आप पैरामीटर को तदनुसार समझते हैं।

+0

ठीक है, यह समझ में आता है। क्या केवल एक सामान्य चर भेजने और बाद में टाइप को अलग करने का कोई तरीका है? – Django

+0

मैं किसी भी गैर-ऑब्जेक्ट मान को ऑब्जेक्ट्स में कनवर्ट करने के लिए 'NSValue' का उपयोग करने का सुझाव दूंगा। अगर आप अपने प्रश्न में समझाएंगे कि आप वास्तव में क्या करने की कोशिश कर रहे हैं तो ठोस सलाह देना आसान होगा। – Caleb

2

आप id प्रकार के पैरामीटर के रूप में सी संरचना या आदिम पास नहीं कर सकते हैं। ऐसा करने के लिए, आपको एनएसएनंबर या NSValue ऑब्जेक्ट में आदिम को लपेटना होगा।

उदा

[self test: [NSNumber numberWithInt: 3.0]]; 

id एक ऑब्जेक्टिव-सी वस्तु के सूचक के रूप में परिभाषित किया गया है।

+0

मुझे पता है कि आप ऐसा नहीं कर सकते हैं। आईडी केवल वस्तुओं के लिए नहीं है प्राइमेटिव्स के लिए। तो क्या उन सभी चरों के लिए एक सामान्य प्रकार नहीं है जिसे मैं बाद में अंतर कर सकता हूं? – Django

+0

नहीं। आप एक 'शून्य *' पास कर सकते हैं, जो किसी भी चीज़ के लिए सूचक है, लेकिन यह बताने का कोई तरीका नहीं होगा कि इसे प्राप्त करने के बाद यह क्या था। – joerick

+1

NSValue अपने 'वैल्यूथबाइट्स: objCType:' विधि के साथ कोई भी डेटा ले सकता है, लेकिन आपको '@ एन्कोड' प्रकार के साथ-साथ 'शून्य *' पॉइंटर को पास करना होगा। – joerick

0

यह ध्यान रखना महत्वपूर्ण है कि आईडी किसी भी उद्देश्य-सी ऑब्जेक्ट का प्रतिनिधित्व करती है। और उद्देश्य-सी ऑब्जेक्ट द्वारा, मेरा मतलब है कि @interface का उपयोग करके परिभाषित किया गया है। यह एक संरचना या आदिम प्रकार (int, char आदि) का प्रतिनिधित्व नहीं करता है।

इसके अलावा, आप ऑब्जेक्टिव-सी ऑब्जेक्ट्स को केवल संदेश ([...] वाक्यविन्यास) भेज सकते हैं, इसलिए आप isKindOf नहीं भेज सकते हैं: सामान्य संरचना या आदिम पर संदेश।

लेकिन आप एक पूर्णांक इत्यादि को एनएसएनंबर में बदल सकते हैं, एक char * एनएसएसटींग में और एनएसओब्जेक्ट-डर्विइड क्लास के अंदर एक संरचना लपेट सकते हैं। फिर वे उद्देश्य-सी वस्तुओं होंगे।

8
#define IS_OBJECT(T) _Generic((T), id: YES, default: NO) 

NSRect a = (NSRect){1,2,3,4}; 
NSString* b = @"whatAmI?"; 
NSInteger c = 9; 

NSLog(@"%@", IS_OBJECT(a)[email protected]"YES":@"NO"); // -> NO 
NSLog(@"%@", IS_OBJECT(b)[email protected]"YES":@"NO"); // -> YES 
NSLog(@"%@", IS_OBJECT(c)[email protected]"YES":@"NO"); // -> NO 

इसके अलावा, बाहर की जाँच विन्सेंट गेबल के The Most Useful Objective-C Code I’ve Ever Written कुछ बहुत आसान सामान @encode() संकलक निर्देश का उपयोग करता है (जो) एक स्ट्रिंग किसी भी प्रकार यह दिया है का वर्णन करने देता है ... "

LOG_EXPR के लिए (एक्स) एक मैक्रो है जो x को प्रिंट करता है, इससे कोई फर्क नहीं पड़ता कि x किस प्रकार का है, प्रारूप-तारों के बारे में चिंता किए बिना (और उदाहरण से संबंधित क्रैश। सी-स्ट्रिंग को एनएसएसटींग के समान ही प्रिंट करना)। यह मैक ओएस एक्स पर काम करता है और आईओएस।

1

#define IS_OBJECT (एक्स) (strchr ("@ #", @encode (typeof (x)) [0])! = शून्य) इस माइक्रो काम करता है जो मैं ढेर अतिप्रवाह में कहीं मिल गया।

3

@alex ग्रे उत्तर काम नहीं किया (या कम से कम आईओएस एसडीके 8.0 पर काम नहीं किया)। आप @ deepax11 उत्तर का उपयोग कर सकते हैं, हालांकि मैं यह इंगित करना चाहता हूं कि यह 'जादू मैक्रो' कैसे काम करता है। यह सिस्टम से प्रदान किए गए प्रकार एन्कोडिंग पर निर्भर करता है। ऐप्पल प्रलेखन के अनुसार:

रनटाइम सिस्टम की सहायता के लिए, कंपाइलर एक वर्ण स्ट्रिंग में प्रत्येक विधि के लिए रिटर्न और तर्क प्रकार को एन्कोड करता है और विधि चयनकर्ता के साथ स्ट्रिंग को जोड़ता है। कोडिंग योजना जो इसका उपयोग करती है वह अन्य संदर्भों में भी उपयोगी है और इसलिए इसे @encode() कंपाइलर निर्देश के साथ सार्वजनिक रूप से उपलब्ध कराया गया है। जब एक प्रकार का विनिर्देश दिया जाता है, तो @encode() टाइप करने वाले स्ट्रिंग एन्कोडिंग देता है। प्रकार एक मूल प्रकार जैसे एक int, एक सूचक, एक टैग की गई संरचना या संघ, या एक वर्ग का नाम हो सकता है, वास्तव में, जिसे C sizeof() ऑपरेटर के लिए तर्क के रूप में उपयोग किया जा सकता है।

मैक्रो अलग तोड़ने के लिए, हम पहले "typeof" हमारे चर मिलता है, तो @encode() उस प्रकार पर कॉल, और अंत में 'वस्तु' और एन्कोडिंग मेज से 'क्लास' प्रकार के लिए दिए गए मान की तुलना करें।

पूर्ण उदाहरण जैसा दिखाई देगा:

const char* myType = @encode(typeof(myVar));//myVar declared somewhere 
    if([@"@" isEqualToString:@(myType)] || [@"#" isEqualToString:@(myType)]) 
    { 
     //myVar is object(id) or a Class 
    } 
    else if (NSNotFound != [[NSString stringWithFormat:@"%s", myType] rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"{}"]].location) 
    { 
     //myVar is struct 
    } 
    else if ([@"i" isEqualToString:@(myType)]) 
    { 
     //my var is int 
    } 

कृपया ध्यान दें कि NSInteger 64-बिट उपकरणों पर 32-बिट उपकरणों पर पूर्णांक वापस आ जाएगी, और लंबे समय। एनकोडिंग की पूर्ण सूची:

‘c’ - char 
‘i’ - int 
’s’ - short 
‘l’ - long 
‘q’ - long long 
‘C’ - unsigned char 
‘I’ - unsigned int 
’S’ - unsigned short 
‘L’ - unsigned long 
‘Q’ - unsigned long long 
‘f’ - float 
‘d’ - double 
‘B’ - C++ bool or a C99 _Bool 
‘v’ - void 
‘*’ - character string(char *) 
‘@’ - object(whether statically typed or typed id) 
‘#’ - class object(Class) 
‘:’ - method selector(SEL) 
‘[<some-type>]’ - array 
‘{<some-name>=<type1><type2>}’ - struct 
‘bnum’ - bit field of <num> bits 
‘^type’ - pointer to <type> 
‘?’ - unknown type(may be used for function pointers) 

पढ़ें