जवाबों:
void *
का अर्थ है "अनकैप्ड / अज्ञात सामग्री के साथ कुछ रैंडम चंक ओ 'मेमोरी का संदर्भ"
id
"अज्ञात वर्ग के कुछ यादृच्छिक उद्देश्य-सी वस्तु का संदर्भ"
अतिरिक्त सिमेंटिक अंतर हैं:
जीसी ओनली या जीसी सपोर्टेड मोड्स के तहत, कंपाइलर टाइप के रेफरेंस के लिए बैरियर लिखेगा id
, लेकिन टाइप के लिए नहीं void *
। संरचनाओं की घोषणा करते समय, यह एक महत्वपूर्ण अंतर हो सकता है। void *_superPrivateDoNotTouch;
यदि _superPrivateDoNotTouch
वास्तव में एक वस्तु है, तो iVars की घोषणा करने से वस्तुओं का समय से पहले रिसाव होगा । ऐसा मत करो।
एक void *
प्रकार के संदर्भ पर एक विधि को लागू करने का प्रयास एक कंपाइलर चेतावनी को रोक देगा।
एक id
प्रकार पर एक विधि को लागू करने का प्रयास केवल तभी चेतावनी देगा जब बुलाया जा रहा विधि @interface
संकलक द्वारा देखी गई किसी भी घोषणा में घोषित नहीं की गई है।
इस प्रकार, किसी को एक वस्तु के रूप में संदर्भित नहीं करना चाहिए void *
। इसी प्रकार, id
किसी वस्तु को संदर्भित करने के लिए टाइप किए गए चर का उपयोग करने से बचना चाहिए । सबसे विशिष्ट वर्ग टाइप किए गए संदर्भ का उपयोग करें। इससे NSObject *
भी बेहतर है id
क्योंकि संकलक, कम से कम, उस संदर्भ के खिलाफ विधि इनवोकेशन का बेहतर सत्यापन प्रदान कर सकता है।
इसका एक सामान्य और मान्य उपयोग void *
अपारदर्शी डेटा संदर्भ के रूप में है जो किसी अन्य एपीआई के माध्यम से पारित किया जाता है।
की sortedArrayUsingFunction: context:
विधि पर विचार करें NSArray
:
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context;
छँटाई समारोह के रूप में घोषित किया जाएगा:
NSInteger mySortFunc(id left, id right, void *context) { ...; }
इस मामले में, NSArray केवल उस context
तर्क के रूप में विधि के तर्क के रूप में आपके पास जो कुछ भी गुजरता context
है। यह सूचक आकार के डेटा का एक अपारदर्शी हंक है, जहां तक NSArray का संबंध है, और आप इसे जिस भी उद्देश्य के लिए उपयोग करना चाहते हैं, उसके लिए स्वतंत्र हैं।
भाषा में एक क्लोजर प्रकार की सुविधा के बिना, यह एक फ़ंक्शन के साथ डेटा के एक हंक के साथ ले जाने का एकमात्र तरीका है। उदाहरण; यदि आप mySortFunc () को केस संवेदी या केस असंवेदनशील के रूप में सशर्त रूप से क्रमबद्ध करना चाहते हैं, जबकि थ्रेड-सुरक्षित होने के बावजूद, आप संदर्भ में केस-संवेदी संकेतक पास करेंगे, संभवत: रास्ते में और रास्ते में कास्टिंग।
नाजुक और त्रुटि प्रवण, लेकिन एकमात्र तरीका।
ब्लॉक इसे हल करते हैं - ब्लॉक सी के लिए क्लोजर हैं। वे क्लैंग में उपलब्ध हैं - http://llvm.org/ और स्नो लेपर्ड ( http://developer.apple.com/library/ios/documentation/Performance) में व्याप्त हैं /Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf )।
id
जवाब क्या होगा। एक id
आसानी से उस वर्ग की एक आवृत्ति का उल्लेख कर सकता है जो अंतर्निहित नहीं है NSObject
। व्यावहारिक रूप से, हालांकि, आपका कथन वास्तविक विश्व व्यवहार से सबसे अच्छा मेल खाता है; आप <NSObject>
फाउंडेशन एपीआई के साथ गैर- कार्यान्वयन कक्षाएं नहीं मिला सकते हैं और बहुत दूर हो सकते हैं, यह निश्चित रूप से निश्चित है!
id
और Class
प्रकारों को एआरसी के तहत अनुरक्षण योग्य वस्तु सूचक के रूप में माना जा रहा है । तो यह धारणा कम से कम एआरसी के तहत सही है।
id एक ऑब्जेक्टिव C ऑब्जेक्ट का पॉइंटर है, जहाँ void * किसी भी चीज़ का पॉइंटर है।
आईडी अज्ञात mthods को कॉल करने से संबंधित चेतावनियों को भी बंद कर देती है, इसलिए उदाहरण के लिए:
[(id)obj doSomethingWeirdYouveNeverHeardOf];
अज्ञात तरीकों के बारे में सामान्य चेतावनी नहीं देंगे। यह निश्चित रूप से, रन समय में एक अपवाद को बढ़ाएगा जब तक कि ओबीज शून्य नहीं होता है या वास्तव में उस पद्धति को लागू नहीं करता है।
अक्सर आपको उपयोग करना चाहिए NSObject*
या id<NSObject>
वरीयता में होना चाहिए id
, जो कम से कम इस बात की पुष्टि करता है कि लौटाई गई वस्तु एक कोको ऑब्जेक्ट है, इसलिए आप सुरक्षित रूप से उस पर बनाए रखने / जारी करने / ऑटोरेलिज जैसे तरीकों का उपयोग कर सकते हैं।
Often you should use NSObject*
बजाय मैं इससे असहमत हूं id
। निर्दिष्ट करके NSObject*
आप वास्तव में स्पष्ट रूप से कह रहे हैं कि ऑब्जेक्ट एक NSObject है। ऑब्जेक्ट के लिए किसी भी विधि को कॉल करने पर एक चेतावनी होगी, लेकिन जब तक कि ऑब्जेक्ट वास्तव में विधि कॉल का जवाब नहीं देता तब तक कोई रनटाइम अपवाद नहीं होगा। चेतावनी स्पष्ट रूप से कष्टप्रद है इसलिए id
बेहतर है। मोटे तौर पर आप उदाहरण के लिए यह कहकर और अधिक विशिष्ट हो सकते हैं id<MKAnnotation>
, जो इस मामले में है कि जो भी वस्तु का मतलब है, वह एमकेएनओनेटेशन प्रोटोकॉल के अनुरूप होना चाहिए।
यदि किसी विधि का रिटर्न प्रकार है id
तो आप किसी भी ऑब्जेक्ट-सी ऑब्जेक्ट को वापस कर सकते हैं।
void
इसका मतलब है, विधि कुछ भी नहीं लौटाएगी।
void *
सिर्फ एक सूचक है। आप पॉइंटर पॉइंट के पते पर कंटेंट को एडिट नहीं कर पाएंगे।
id
ऑब्जेक्टिव-सी ऑब्जेक्ट का पॉइंटर है। void *
किसी भी चीज का सूचक है । आप void *
इसके बजाय उपयोग कर सकते हैं id
, लेकिन यह अनुशंसित नहीं है क्योंकि आपको कभी भी किसी चीज़ के लिए संकलक चेतावनी नहीं मिलेगी।
आप 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 ।
void *
टाइप किए गए चर सबसे निश्चित रूप से विधि इनवोकेशन का लक्ष्य हो सकते हैं- यह एक चेतावनी है, त्रुटि नहीं। इतना ही नहीं, आप यह कर सकते हैं: int i = (int)@"Hello, string!";
और साथ पालन करें printf("Sending to an int: '%s'\n", [i UTF8String]);
:। यह एक चेतावनी है, एक त्रुटि नहीं (और बिल्कुल अनुशंसित नहीं, न ही पोर्टेबल)। लेकिन आप इन चीजों को क्यों कर सकते हैं इसका कारण सभी बुनियादी सी है
/// 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.h से है, इसलिए ऐसा लग रहा है कि id objc_object संरचना का एक उदाहरण है और isa पॉइंटर किसी भी ऑब्जेक्टिव C क्लास ऑब्जेक्ट के साथ बाँध सकता है, जबकि void * केवल एक अनइंस्टॉल पॉइंटर है।
मेरी समझ यह है कि आईडी एक संकेतक को एक वस्तु का प्रतिनिधित्व करता है जबकि शून्य * वास्तव में कुछ भी इंगित कर सकता है, जब तक कि आप इसे उस प्रकार के लिए डाल दें जिसे आप इसका उपयोग करना चाहते हैं
पहले से ही कहा गया है के अलावा, संग्रह से संबंधित वस्तुओं और संकेत के बीच अंतर है। उदाहरण के लिए, यदि आप NSArray में कुछ डालना चाहते हैं, तो आपको एक ऑब्जेक्ट (प्रकार "आईडी") की आवश्यकता होती है, और आप वहां एक कच्चे डेटा पॉइंटर का उपयोग नहीं कर सकते हैं (प्रकार "शून्य *")। आप इसे संग्रह के अंदर उपयोग [NSValue valueWithPointer:rawData]
करने के void *rawDdata
लिए "आईडी" प्रकार में परिवर्तित करने के लिए उपयोग कर सकते हैं। सामान्य तौर पर "आईडी" अधिक लचीली होती है और इसमें संलग्न वस्तुओं से संबंधित शब्दार्थ अधिक होते हैं। यहाँ पर और भी उदाहरण दिए गए हैं, जो यहाँ पर Objective C के id प्रकार की व्याख्या कर रहे हैं ।
id
को जवाब देने के लिए मान लिया गया है-retain
और-release
जबकिvoid*
कैली के लिए यह पूरी तरह से अपारदर्शी है। आप एक मनमाने ढंग से पॉइंटर को पास नहीं कर सकते-performSelector:withObject:afterDelay:
(यह ऑब्जेक्ट को बनाए रखता है), और आप यह नहीं मान सकते हैं कि+[UIView beginAnimations:context:]
संदर्भ बरकरार रहेगा (एनीमेशन प्रतिनिधि को संदर्भ का स्वामित्व बनाए रखना चाहिए; UIKit एनीमेशन प्रतिनिधि को बरकरार रखता है)।