2009-08-20 17 views

उत्तर

231

void * साधन

id का अर्थ है "अज्ञात वर्ग के कुछ यादृच्छिक ऑब्जेक्टिव-सी वस्तु के लिए एक संदर्भ" "कुछ यादृच्छिक हिस्सा ओ 'untyped/अज्ञात सामग्री के साथ स्मृति के लिए एक संदर्भ"

अतिरिक्त अर्थ हैं मतभेद:

  • जीसी के तहत केवल या जीसी समर्थित मोड, संकलक प्रकार id के संदर्भ के लिए लिखने बाधाओं फेंकना होगा, लेकिन प्रकारके लिए नहीं। संरचनाओं की घोषणा करते समय, यह एक महत्वपूर्ण अंतर हो सकता है। void *_superPrivateDoNotTouch; जैसे iVars घोषित करने से _superPrivateDoNotTouch वास्तव में ऑब्जेक्ट होने पर ऑब्जेक्ट्स के समय से पहले काटने का कारण बन जाएगा। ऐसा मत करो।

  • void * प्रकार के संदर्भ पर एक विधि का आह्वान करने का प्रयास करने से एक कंपाइलर चेतावनी को बाधित कर दिया जाएगा।

  • एक id प्रकार पर एक विधि को लागू करने की केवल चेतावनी देगा अगर विधि बुलाया जा रहा है @interface घोषणाओं संकलक द्वारा देखा में से किसी में घोषित नहीं किया गया है प्रयास करते हैं।

इस प्रकार, किसी को किसी ऑब्जेक्ट को void * के रूप में संदर्भित नहीं करना चाहिए। इसी तरह, किसी ऑब्जेक्ट को संदर्भित करने के लिए id टाइप किए गए चर का उपयोग करने से बचना चाहिए। सबसे विशिष्ट वर्ग टाइप किए गए संदर्भ का उपयोग करें जो आप कर सकते हैं। यहां तक ​​कि NSObject *id से बेहतर है क्योंकि संकलक, कम से कम, उस संदर्भ के विरुद्ध विधि आमंत्रण के बेहतर सत्यापन प्रदान कर सकता है।

void * का एक सामान्य और वैध उपयोग किसी अन्य एपीआई के माध्यम से पारित एक अपारदर्शी डेटा संदर्भ के रूप में है।

पर विचार करें NSArray की sortedArrayUsingFunction: context: विधि:

- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context; 

छँटाई समारोह के रूप में घोषित किया जाएगा:

NSInteger mySortFunc(id left, id right, void *context) { ...; } 

इस मामले में, NSArray केवल गुजरता है जो कुछ भी आप के लिए context तर्क के रूप में में पारित context तर्क के माध्यम से विधि। यह पॉइंटर आकार के डेटा का एक अपारदर्शी हिस्सा है, जहां तक ​​एनएसएआरएआरई का संबंध है, और आप जो भी उद्देश्य चाहते हैं उसका उपयोग करने के लिए स्वतंत्र हैं।

भाषा में एक बंद प्रकार की विशेषता के बिना, यह एक समारोह के साथ डेटा के एक हंक के साथ ले जाने का एकमात्र तरीका है। उदाहरण; अगर आप mySortFunc() को सशर्त रूप से केस संवेदनशील या केस असंवेदनशील के रूप में सॉर्ट करना चाहते थे, जबकि अभी भी थ्रेड-सुरक्षित भी है, तो आप संदर्भ में केस-केस-सेंसिटिव इंडिकेटर पास करेंगे, संभवतः रास्ते में और रास्ते में कास्टिंग कर सकते हैं।

बेकार और त्रुटि प्रवण, लेकिन एकमात्र तरीका।

ब्लाकों इस का समाधान - ब्लॉक बंद सी के लिए वे बजना में उपलब्ध हैं कर रहे हैं - http://llvm.org/ और हिमपात तेंदुए (http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf) में व्यापक हैं।

+0

इसके अतिरिक्त, मुझे पूरा यकीन है कि 'id' को' -retain' और '-release' का जवाब देने के लिए माना जाता है, जबकि 'void *' पूरी तरह से कैली के लिए अपारदर्शी है। आप 'मनोनीत चयनकर्ता' के साथ एक मनमाना सूचक नहीं पारित कर सकते हैं: ऑब्जेक्ट: बाद में: '(यह ऑब्जेक्ट को बरकरार रखता है), और आप यह नहीं मान सकते कि' + [UIView प्रारंभएनीमेशन: संदर्भ:] 'संदर्भ को बनाए रखेगा (एनीमेशन प्रतिनिधि संदर्भ के स्वामित्व को बनाए रखना चाहिए; UIKit एनीमेशन प्रतिनिधि को बरकरार रखता है)। –

+3

किसी आईडी आईडी के जवाब के बारे में कोई धारणा नहीं की जा सकती है। एक 'आईडी' आसानी से उस वर्ग के उदाहरण को संदर्भित कर सकता है जो 'NSObject' से निहित नहीं है। व्यावहारिक रूप से बोलते हुए, हालांकि, आपका कथन वास्तविक दुनिया व्यवहार से मेल खाता है; आप फाउंडेशन एपीआई के साथ कक्षाओं को कार्यान्वित करने के लिए गैर-' 'मिश्रण नहीं कर सकते हैं और बहुत दूर हो सकते हैं, यह निश्चित रूप से निश्चित रूप से है! – bbum

+2

अब 'आईडी' और 'कक्षा' प्रकारों को एआरसी के तहत [* retainable ऑब्जेक्ट पॉइंटर *] (http://clang.llvm.org/docs/AutomaticReferenceCounting.html#objects) के रूप में माना जा रहा है। तो कम से कम एआरसी के तहत धारणा सच है। – Eonil

8

यदि किसी विधि के पास id का रिटर्न प्रकार है तो आप कोई ऑब्जेक्टिव-सी ऑब्जेक्ट वापस कर सकते हैं।

void का अर्थ है, विधि कुछ भी वापस नहीं करेगी।

void * सिर्फ एक सूचक है। आप पॉइंटर पॉइंट के पते पर सामग्री को संपादित करने में सक्षम नहीं होंगे।

+2

चूंकि यह किसी विधि के वापसी मूल्य पर लागू होता है, अधिकतर सही। चूंकि यह घोषित चर या तर्क पर लागू होता है, बिल्कुल नहीं। और यदि आप सामग्री को पढ़ना/लिखना चाहते हैं तो आप हमेशा एक (शून्य *) को एक और विशिष्ट प्रकार पर डाल सकते हैं - ऐसा नहीं करना कि ऐसा करना एक अच्छा विचार है। – bbum

2

मेरे समझ कि आईडी एक वस्तु के लिए सूचक का प्रतिनिधित्व करता है, जबकि शून्य * वास्तव में, जब तक कि आप तो आप किस प्रकार के रूप में

+0

यदि आप आईडी सहित कुछ ऑब्जेक्ट प्रकार (void *) से कास्टिंग कर रहे हैं, तो आप इसे गलत कर रहे हैं। ऐसा करने के कारण हैं, लेकिन वे कुछ डिज़ाइन त्रुटियों के बारे में कुछ, दूर, और लगभग हमेशा संकेतक हैं। – bbum

+1

उद्धरण "ऐसा करने के कारण हैं, लेकिन वे" सच हैं "के बीच बहुत कम हैं। यह स्थिति पर निर्भर करता है। हालांकि मैं कुछ संदर्भ के साथ "आप इसे गलत कर रहे हैं" जैसे कंबल स्टेटमेंट नहीं बनायेगा। – hhafez

+0

मैं एक कंबल कथन बनाउंगा; शून्य के साथ गलत प्रकार के साथ गलत प्रकार के कास्टिंग करने के कारण बहुत अधिक शापित बग का शिकार करना और ठीक करना था।एक अपवाद कॉलबैक आधारित एपीआई है जो एक शून्य * संदर्भ तर्क लेता है जिसका अनुबंध कहता है कि संदर्भ कॉलबैक सेट करने और कॉलबैक प्राप्त करने के बीच छेड़छाड़ नहीं रहेगा। – bbum

19

आईडी इसका उपयोग करना चाहते करने के लिए इसे डाली कुछ भी करने के लिए इंगित कर सकते हैं एक के लिए सूचक है है उद्देश्य सी ऑब्जेक्ट, जहां शून्य * किसी भी चीज़ के लिए सूचक है।

आईडी भी अज्ञात mthods बुला से संबंधित चेतावनी बंद हो जाती है, उदाहरण के लिए इतना:

[(id)obj doSomethingWeirdYouveNeverHeardOf];

अज्ञात तरीकों के बारे में सामान्य चेतावनी नहीं देंगे। यह निश्चित रूप से, रन टाइम पर अपवाद उठाएगा जब तक ओबीजी शून्य न हो या वास्तव में उस विधि को लागू न करे।

अक्सर आप id वरीयता में NSObject* या id<NSObject> का उपयोग करना चाहिए, जो कम से कम इस बात की पुष्टि है कि वस्तु लौट आए, एक कोको वस्तु है, तो आप सुरक्षित रूप से इस पर बनाए रखने/रिलीज/autorelease तरह तरीकों का उपयोग कर सकते हैं।

+2

विधि आमंत्रण के लिए, लक्ष्य का लक्ष्य (आईडी) एक चेतावनी उत्पन्न करेगा यदि लक्षित विधि कहीं भी घोषित नहीं की गई है। इस प्रकार, आपके उदाहरण में, DoSomethingWeirdYouveNeverHeardOf को वहां कहीं भी घोषित नहीं किया जाना चाहिए था कि चेतावनी न हो। – bbum

+0

आप सही सही हैं, एक बेहतर उदाहरण भंडारण नीति जैसा कुछ होगा। –

+0

@ पीटर NLewis मैं 'आईडी' के बजाय अक्सर 'NSObject * का उपयोग करना चाहिए' पर असहमत हूं। 'NSObject *' निर्दिष्ट करके आप वास्तव में स्पष्ट रूप से कह रहे हैं कि ऑब्जेक्ट एक NSObject है। ऑब्जेक्ट को किसी भी विधि कॉल के परिणामस्वरूप चेतावनी होगी, लेकिन तब तक कोई रनटाइम अपवाद नहीं होगा जब तक कि ऑब्जेक्ट वास्तव में विधि कॉल का जवाब न दे। चेतावनी स्पष्ट रूप से परेशान है इसलिए 'आईडी' बेहतर है। मोटे तौर पर आप उदाहरण के लिए अधिक विशिष्ट हो सकते हैं उदाहरण के लिए 'id ' कह रहा है, जो इस मामले में वस्तु का अर्थ है, यह एमकेएनोटेशन प्रोटोकॉल के अनुरूप होना चाहिए। – pnizzle

7

id एक उद्देश्य-सी ऑब्जेक्ट के लिए एक सूचक है। void *कुछ भी पर एक सूचक है। आप id के बजाय void * का उपयोग कर सकते हैं, लेकिन इसकी अनुशंसा नहीं की जाती है क्योंकि आपको कभी भी किसी भी चीज़ के लिए कंपाइलर चेतावनियां नहीं मिलती हैं।

आप stackoverflow.com/questions/466777/whats-the-difference-between-declaring-a-variable-id-and-nsobject और unixjunkie.blogspot.com/2008/03/id-vs-nsobject-vs-id.html देख सकते हैं।

+1

काफी नहीं। (शून्य *) टाइप किए गए चर विधि विधियों का लक्ष्य नहीं हो सकते हैं। इसके परिणामस्वरूप "चेतावनी: संकलक से अमान्य रिसीवर प्रकार 'शून्य *'" होता है। – bbum

+0

@bbum: 'शून्य *' टाइप किए गए चर सबसे निश्चित रूप से विधि आमंत्रण का लक्ष्य हो सकते हैं- यह एक चेतावनी है, त्रुटि नहीं। इतना ही नहीं, आप यह कर सकते हैं: 'int i = (int) @ "हैलो, स्ट्रिंग!";' और इसके साथ अनुवर्ती करें: 'printf ("int में भेजना:'% s '\ n", [i UTF8String ]); '। यह एक चेतावनी है, एक त्रुटि नहीं (और बिल्कुल अनुशंसित नहीं है, न ही पोर्टेबल)। लेकिन कारण यह है कि आप इन चीजों को क्यों कर सकते हैं सभी मूल सी – johne

+0

क्षमा करें। तुम सही हो; यह एक चेतावनी है, एक त्रुटि नहीं। मैं सिर्फ चेतावनियों को हमेशा और हर जगह त्रुटियों के रूप में मानता हूं। – bbum

4
/// Represents an instance of a class. 
struct objc_object { 
    Class isa OBJC_ISA_AVAILABILITY; 
}; 

/// A pointer to an instance of a class. 
typedef struct objc_object *id; 

ऊपर कोड तो लग रहा है आईडी की तरह objc_object struct और इसा सूचक का एक उदाहरण किसी भी उद्देश्य सी क्लास वस्तु के साथ बाध्य कर सकते हैं, जबकि शून्य * सिर्फ एक untyped सूचक है, objc.h से है।

0

जो पहले से ही कहा गया है, इसके अलावा, संग्रह से संबंधित वस्तुओं और पॉइंटर्स के बीच एक अंतर है। उदाहरण के लिए, यदि आप एनएसएआरएआरई में कुछ डालना चाहते हैं, तो आपको किसी ऑब्जेक्ट (टाइप "आईडी") की आवश्यकता है, और आप कच्चे डेटा पॉइंटर का उपयोग नहीं कर सकते हैं (प्रकार "शून्य *")। आप संग्रह के अंदर उपयोग करने के लिए "आईडी" प्रकार में void *rawDdata को परिवर्तित करने के लिए [NSValue valueWithPointer:rawData] का उपयोग कर सकते हैं। आम तौर पर "आईडी" अधिक लचीला होता है और इसके साथ जुड़ी वस्तुओं से संबंधित अधिक अर्थशास्त्र होता है। id type of Objective C here समझाते हुए और उदाहरण हैं।

संबंधित मुद्दे