एआरसी के तहत हमें किन स्थितियों में __autoreleasing owner क्वालीफायर लिखना होगा?


118

मैं पहेली को पूरा करने की कोशिश कर रहा हूं।

__strongNSObject, NSString, आदि जैसे सभी ऑब्जेक्टिव-सी मेंटेनेंस ऑब्जेक्ट पॉइंटर्स के लिए डिफ़ॉल्ट है। यह एक मजबूत संदर्भ है। एआरसी -releaseगुंजाइश के अंत में इसे संतुलित करता है।

__unsafe_unretainedपुराने तरीके के बराबर है। यह एक कमजोर सूचक के लिए प्रयोग किए जाने योग्य वस्तु को बनाए रखने के बिना है।

__weakकी तरह है __unsafe_unretainedसिवाय इसके कि यह एक स्वत: शून्यीकरण को कमजोर संदर्भ अर्थ सूचक ही संदर्भित वस्तु पुनः आवंटित की जाती है के रूप में नहीं के बराबर करने के लिए निर्धारित किया जाएगा कि है। यह खतरे के बिंदुओं और EXC_BAD_ACCESS त्रुटियों को समाप्त करता है।

लेकिन वास्तव में क्या __autoreleasingअच्छा है? जब मुझे इस क्वालीफायर का उपयोग करने की आवश्यकता होती है, तो मुझे व्यावहारिक उदाहरण खोजने में कठिन समय लगता है। मेरा मानना ​​है कि यह केवल उन कार्यों और विधियों के लिए है जो एक पॉइंटर-पॉइंटर की अपेक्षा करते हैं जैसे:

- (BOOL)save:(NSError**);

या

NSError *error = nil;
[database save:&error];

जिसके तहत एआरसी को इस तरह घोषित किया जाना है:

- (BOOL)save:(NSError* __autoreleasing *);

लेकिन यह बहुत अस्पष्ट है और मैं पूरी तरह से समझना चाहूंगा कि क्यों । कोड स्निपेट मुझे लगता है कि दो सितारों के __autoreleasing inbetween को जगह देता है, जो मुझे अजीब लगता है। प्रकार है NSError**(NSError के लिए एक पॉइंटर-पॉइंटर), इसलिए __autoreleasingतारों को इनबिल्ट न करके केवल सामने ही क्यों रखें NSError**?

इसके अलावा, ऐसी अन्य परिस्थितियां भी हो सकती हैं जिनमें मुझे भरोसा करना चाहिए __autoreleasing


1
मेरे पास यही प्रश्न है और नीचे दिए गए उत्तर पूरी तरह से आश्वस्त नहीं हैं ... उदाहरण के लिए, सिस्टम ने इंटरफेस क्यों नहीं दिया है जो NSError लेते हैं ** आपके जैसे __autoreleasing डेकोरेटर के साथ घोषित किए गए तर्क और आर्क रिलीज़ नोट्स के लिए संक्रमण वे कहते हैं होना चाहिए? उदाहरण के लिए, NSFileManager.h में इनमें से कई दिनचर्या में से कोई है ??
पिताजी

जवाबों:


67

आप सही हे। जैसा कि आधिकारिक दस्तावेज बताते हैं:

__autoreleasing तर्कों को निरूपित करने के लिए जो संदर्भ (आईडी *) द्वारा पारित किए जाते हैं और रिटर्न पर ऑटोरेल्ड होते हैं।

एआरसी संक्रमण गाइड में यह सब बहुत अच्छी तरह से समझाया गया है ।

आपके NSError उदाहरण में, घोषणा का अर्थ है __strong, स्पष्ट रूप से:

NSError * e = nil;

में तब्दील हो जाएगा:

NSError * __strong error = nil;

जब आप अपनी saveविधि कहते हैं :

- ( BOOL )save: ( NSError * __autoreleasing * );

कंपाइलर को तब एक अस्थायी वैरिएबल बनाना होगा, जिस पर सेट किया गया है __autoreleasing। इसलिए:

NSError * error = nil;
[ database save: &error ];

में तब्दील हो जाएगा:

NSError * __strong error = nil;
NSError * __autoreleasing tmpError = error;
[ database save: &tmpError ];
error = tmpError;

आप __autoreleasingसीधे त्रुटि ऑब्जेक्ट घोषित करके इससे बच सकते हैं।


3
नहीं, __autoreleasingकेवल संदर्भ द्वारा पारित तर्कों के लिए उपयोग किया जाता है। यह एक विशेष मामला है, क्योंकि आपको एक ऑब्जेक्ट के पॉइंटर को पॉइंटर मिला है। सुविधा निर्माणकर्ताओं की तरह सामान के मामले में ऐसा नहीं है, क्योंकि वे केवल एक ऑब्जेक्ट के लिए एक पॉइंटर लौटाते हैं, और एआरसी इसे स्वचालित रूप से संभालती है।
मैकडेम

7
__Autoreleasing Qualifier को तारों को Inbetween क्यों रखा गया है, न कि NSError ** के सामने? यह मेरे लिए अजीब लगता है क्योंकि प्रकार NSError ** है। या ऐसा इसलिए है क्योंकि यह इंगित करने की कोशिश कर रहा है कि इंगित-से NSError * सूचक को ऑटोरेल्ड ऑब्जेक्ट की ओर इशारा करते हुए योग्य होना चाहिए?
गर्व सदस्य

1
@ पहला सदस्य आपकी पहली टिप्पणी के संबंध में - यह गलत है (यदि मैं आपको सही तरीके से समझता हूं) - नीचे ग्लेन लो का जवाब देखें। त्रुटि ऑब्जेक्ट को बनाया गया है और एक ऑटोरेलिएजिंग चर (जिसे आप पास किया गया है) को सेव फंक्शन के अंदर सौंपा गया है । यह असाइनमेंट उस समय के लिए ऑब्जेक्ट को बनाए रखा जाता है और ऑटोरेलिज्ड होता है। सहेजें फ़ंक्शन की घोषणा हमें इसे ऑटोरिलिज़िंग वैरिएबल के अलावा कुछ भी भेजने से रोकती है क्योंकि यह वही है जिसकी आवश्यकता है - यही कारण है कि कंपाइलर एक अस्थायी चर बनाता है यदि हम कोशिश करते हैं।
कॉलिन

2
तो Apple इंटरफेस में से कोई भी ऐसा क्यों नहीं लगता है? उदाहरण के लिए, NSFileManager.h में सब कुछ?
पिताजी

1
@Acर्मेड: बस संयोग से मैंने देखा कि आपके उत्तर को संपादित किया गया है ( stackoverflow.com/users/12652/comptrol द्वारा ) और मुझे आभास है कि कम से कम आपके पहले उदाहरण में परिवर्तन ("संक्षेप में ...) में बदल जाएगा ...) गलत हैं, क्योंकि __strong क्वालीफायर को दूसरी पंक्ति से पहली पंक्ति में स्थानांतरित कर दिया गया है। शायद आप यह देख सकते हैं।
मार्टिन आर

34

मैकमेड के उत्तर पर और प्राउड मेंबर के फॉलो अप कमेंट में सवाल करें, (इसे भी टिप्पणी के रूप में पोस्ट किया होगा, लेकिन यह अधिकतम वर्ण संख्या से अधिक है):

यही कारण है कि __autoreleasing के चर क्वालिफायर को दो तारों के बीच रखा गया है।

प्रस्तावना के लिए, एक गुणक के साथ ऑब्जेक्ट पॉइंटर घोषित करने का सही सिंटैक्स है:

NSError * __qualifier someError;

संकलक इसे माफ करेगा:

__qualifier NSError *someError;

लेकिन यह सही नहीं है। Apple ARC संक्रमण मार्गदर्शिका देखें (जो अनुभाग शुरू होता है "आपको चर को सही ढंग से सजाना चाहिए ...")।

हाथ में प्रश्न को संबोधित करने के लिए: एक डबल पॉइंटर में एआरसी मेमोरी मैनेजमेंट क्वालीफायर नहीं हो सकता क्योंकि एक पॉइंटर जो एक मेमोरी एड्रेस को इंगित करता है वह एक आदिम प्रकार का एक पॉइंटर है, जो ऑब्जेक्ट के लिए पॉइंटर नहीं है। हालाँकि, जब आप डबल पॉइंटर घोषित करते हैं, तो एआरसी यह जानना चाहता है कि दूसरे पॉइंटर के लिए मेमोरी मैनेजमेंट नियम क्या हैं। यही कारण है कि डबल पॉइंटर चर के रूप में निर्दिष्ट किया गया है:

SomeClass * __qualifier *someVariable;

तो एक विधि तर्क के मामले में जो एक डबल NSError पॉइंटर है, डेटा प्रकार के रूप में घोषित किया गया है:

- (BOOL)save:(NSError* __autoreleasing *)errorPointer;

जो अंग्रेजी में "एक __autoreleasing NSError ऑब्जेक्ट पॉइंटर को पॉइंटर" कहता है।


15

निश्चित एआरसी विनिर्देश का कहना है कि

__Autoreleasing वस्तुओं के लिए, नया पॉइंटर बनाए रखा जाता है, ऑटोरेलिज्ड होता है, और आदिम शब्दार्थ का उपयोग करके अंतराल में संग्रहीत किया जाता है।

उदाहरण के लिए, कोड

NSError* __autoreleasing error = someError;

वास्तव में परिवर्तित हो जाता है

NSError* error = [[someError retain] autorelease];

... यही कारण है कि जब आप एक पैरामीटर है NSError* __autoreleasing * errorPointer, तो यह काम करता है , कहा जाता है कि विधि तब त्रुटि को असाइन करेगी *errorPointerऔर उपरोक्त शब्दार्थ किक में किक करेगा।

आप __autoreleasingएक अलग संदर्भ में एक ऑटोक्रेसी पूल में एआरसी ऑब्जेक्ट को मजबूर करने के लिए उपयोग कर सकते हैं , लेकिन यह बहुत उपयोगी नहीं है क्योंकि एआरसी केवल विधि वापसी पर ऑटोरेलिज पूल का उपयोग करता है और पहले से ही स्वचालित रूप से संभालता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.