एआरसी के साथ @autoreleasepool की अभी भी आवश्यकता क्यों है?


191

एआरसी (ऑटोमैटिक रेफरेंस काउंटिंग) वाले अधिकांश भाग के लिए, हमें ऑब्जेक्ट-सी ऑब्जेक्ट्स के साथ स्मृति प्रबंधन के बारे में सोचने की आवश्यकता नहीं है। इसे NSAutoreleasePoolअब और बनाने की अनुमति नहीं है, हालांकि एक नया वाक्यविन्यास है:

@autoreleasepool {
    
}

मेरा सवाल यह है कि जब मुझे मैन्युअल रूप से रिलीज़ / ऑटोरेलिंग नहीं होना चाहिए तो मुझे इसकी आवश्यकता क्यों होगी?


संपादित करें: यह समझने के लिए कि मुझे सभी समाचारों और टिप्पणियों से क्या मिला:

नया सिंटैक्स:

@autoreleasepool { … } के लिए नया वाक्यविन्यास है

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

[pool drain];

अधिक महत्वपूर्ण बात:

  • एआरसी का उपयोग करता है autoreleaseऔर साथ ही release
  • ऐसा करने के लिए उसे एक ऑटो रिलीज़ पूल की आवश्यकता है।
  • ARC आपके लिए ऑटो रिलीज़ पूल नहीं बनाता है। तथापि:
    • हर कोको ऐप के मुख्य धागे में पहले से ही एक ऑटोरेलिज पूल है।
  • दो मौके हैं जब आप इसका उपयोग करना चाहते हैं @autoreleasepool:
    1. जब आप द्वितीयक थ्रेड में होते हैं और कोई ऑटो रिलीज़ पूल नहीं होता है, तो आपको लीक को रोकने के लिए अपना स्वयं का बनाना होगा, जैसे कि myRunLoop(…) { @autoreleasepool { … } return success; }
    2. जब आप अधिक स्थानीय पूल बनाना चाहते हैं, जैसा कि @mattjgalloway ने अपने उत्तर में दिखाया है।

1
एक तीसरा अवसर भी है: जब आप कुछ ऐसा विकसित करते हैं जो UIKit या NSFoundation से संबंधित नहीं है। कुछ ऐसा है जो कमांड लाइन टूल या तो का उपयोग करता है
गार्निक

जवाबों:


215

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

नए क्लैंग 3.0 कंपाइलर और एआरसी के साथ किए गए अन्य परिवर्तनों में से एक यह है कि उन्हें कंपाइलर निर्देश के NSAutoReleasePoolसाथ बदल दिया गया @autoreleasepoolNSAutoReleasePoolहमेशा एक विशेष "वस्तु" का एक सा था और उन्होंने इसे इसलिए बनाया ताकि एक का उपयोग करने का वाक्यविन्यास किसी वस्तु के साथ भ्रमित न हो ताकि यह आम तौर पर थोड़ा अधिक सरल हो।

तो मूल रूप से, आपको जरूरत है @autoreleasepoolक्योंकि चिंता करने के लिए अभी भी ऑटो रिलीज पूल हैं। आपको बस इसमें जोड़ने की चिंता करने की आवश्यकता नहीं हैautorelease कॉल ।

ऑटो रिलीज़ पूल का उपयोग करने का एक उदाहरण:

- (void)useALoadOfNumbers {
    for (int j = 0; j < 10000; ++j) {
        @autoreleasepool {
            for (int i = 0; i < 10000; ++i) {
                NSNumber *number = [NSNumber numberWithInt:(i+j)];
                NSLog(@"number = %p", number);
            }
        }
    }
}

एक बेहद जटिल उदाहरण, निश्चित रूप से, लेकिन अगर आपके पास @autoreleasepoolबाहरी- forलूप नहीं है तो आप 100000000 वस्तुओं को बाद में जारी करेंगे, जबकि बाहरी- forलूप के प्रत्येक बार 10000 के बजाय ।

अपडेट: इस उत्तर को भी देखें - https://stackoverflow.com/a/7950636/1068248 - @autoreleasepoolएआरसी के लिए कुछ भी क्यों नहीं करना है।

अद्यतन: मैंने यहाँ क्या हो रहा है और इसे अपने ब्लॉग पर लिखा है , के आंतरिक विवरण पर एक नज़र डाली । अगर आप वहां नज़र डालते हैं तो आप देखेंगे कि एआरसी क्या कर रहा है और नई शैली @autoreleasepoolऔर यह कैसे एक गुंजाइश का परिचय देता है कंपाइलर द्वारा इसका उपयोग इस बात की जानकारी के लिए किया जाता है कि क्या रिटर्न्स, रिलीज़ और ऑटोरेलिस की आवश्यकता है।


11
इसे बरकरार रखने से छुटकारा नहीं मिलता है। यह उन्हें आपके लिए जोड़ता है। संदर्भ की गिनती अभी भी जारी है, यह सिर्फ स्वचालित है। इसलिए ऑटोमैटिक रेफरेंस काउंटिंग :-D।
मटजग्लौय

6
तो यह @autoreleasepoolमेरे लिए भी क्यों नहीं जोड़ता है? यदि मैं नियंत्रित नहीं कर रहा हूं कि ऑटोरेलिज्ड हो जाता है या रिहा हो जाता है (एआरसी मेरे लिए ऐसा करता है), मुझे कैसे पता होना चाहिए कि ऑटोरेलिज पूल कब स्थापित किया जाए?
mk12

5
लेकिन आपका ऑटो रिलीज पूल अभी भी कहां जाता है, इस पर आपका नियंत्रण है। डिफ़ॉल्ट रूप से आपके पूरे ऐप में एक लपेटा हुआ है, लेकिन आप और अधिक चाहते हैं।
२१:२ay बजे मटजग्लौय

5
अच्छा प्रश्न। आपको बस "जानना" है। एक जीसी भाषा में एक के समान एक को जोड़ने के बारे में सोचें, कचरा इकट्ठा करने वाले को आगे बढ़ने और अब एक चक्र चक्र चलाने के लिए एक संकेत जोड़ें। हो सकता है कि आपको पता हो कि एक टन वस्तुओं को हटाने की तैयारी है, आपके पास एक लूप है जो अस्थायी वस्तुओं का एक गुच्छा आवंटित करता है, इसलिए आप "जानते हैं" (या उपकरण आपको बता सकते हैं :) कि लूप के चारों ओर एक रिलीज पूल जोड़ना एक होगा अच्छा विचार।
ग्राहम पर्क्स

6
लूपिंग उदाहरण ऑटोरेलिज़ के बिना पूरी तरह से ठीक काम करता है: चर के दायरे से बाहर जाने पर प्रत्येक वस्तु को हटा दिया जाता है। ऑटोरेलिज़ के बिना कोड चलाना स्मृति की एक निरंतर मात्रा लेता है और इंगित करता है कि पुन: उपयोग किया जा रहा है, और किसी ऑब्जेक्ट के डीललोक पर एक ब्रेकपॉइंट लगाने से पता चलता है कि यह लूप के माध्यम से हर बार एक बार कॉल किया जाता है, जब objc_storeStrong कहा जाता है। हो सकता है कि OSX यहां कुछ गूंगा करता है, लेकिन iOS पर ऑटोरेलिजपूल पूरी तरह से अनावश्यक है।
ग्लेन मेनार्ड

16

@autoreleasepoolकुछ भी ऑटोरेलिज नहीं करता है। यह एक ऑटोरेलिज़ पूल बनाता है, ताकि जब ब्लॉक का अंत हो जाए, तो कोई भी ऑब्जेक्ट जो एआरसी द्वारा ऑटोरेल्ड किया गया था, जबकि ब्लॉक सक्रिय था रिलीज संदेश भेजे जाएंगे। Apple के एडवांस्ड मेमोरी मैनेजमेंट प्रोग्रामिंग गाइड ने इस प्रकार बताया:

ऑटोरेलिज़ पूल ब्लॉक के अंत में, ब्लॉक के भीतर एक ऑटोरेलिज़ संदेश प्राप्त करने वाली वस्तुओं को एक रिलीज़ संदेश भेजा जाता है - किसी ऑब्जेक्ट को रिलीज़ संदेश प्राप्त होता है, जब इसे ब्लॉक के भीतर एक ऑटोरेलिज़ संदेश भेजा जाता था।


1
जरुरी नहीं। ऑब्जेक्ट को एक releaseसंदेश प्राप्त होगा, लेकिन अगर रिटेन काउंट है> 1 तो ऑब्जेक्ट को नहीं हटाया जाएगा।
andybons

@ कैंडी: अद्यतन; धन्यवाद। क्या यह पूर्व-एआरसी व्यवहार से बदलाव है?
outis

यह गलत है। ARC द्वारा जारी की गई वस्तुओं को ARC द्वारा रिलीज़ होते ही, ऑटोरेलिज़ पूल के साथ या उसके बिना रिलीज़ संदेश भेजे जाएंगे।
ग्लेन मेनार्ड

7

लोग अक्सर एआरसी को किसी तरह के कचरा संग्रह या पसंद के लिए गलत समझते हैं। सच्चाई यह है कि, कुछ समय बाद Apple (llvm और क्लैंग प्रोजेक्ट्स के लिए धन्यवाद) के लोगों को एहसास हुआ कि ऑब्जेक्टिव-सी के मेमोरी एडमिनिस्ट्रेशन (सभी retainsऔर releases, आदि) को कंपाइल टाइम पर पूरी तरह से ऑटोमेट किया जा सकता है । यह, केवल कोड को पढ़ने से पहले ही चलाया जाता है! :)

ऐसा करने के लिए केवल एक ही शर्त है: हमें नियमों का पालन करना चाहिए , अन्यथा कंपाइलर समय पर प्रक्रिया को स्वचालित नहीं कर पाएगा। तो, यह सुनिश्चित करें कि हम कभी नहीं नियमों को तोड़ने के लिए, हम करने की अनुमति नहीं स्पष्ट रूप से लिखने release, retainआदि, जो कॉल स्वचालित रूप से संकलक द्वारा हमारे कोड में इंजेक्ट किया जाता है। इसलिए आंतरिक रूप से हम अभी भी है autoreleaseरों, retain, release, आदि यह सिर्फ हम उन्हें अब और लिखने की जरूरत नहीं है है।

एआरसी का संकलन समय पर स्वचालित है, जो कचरे के संग्रह की तरह रन टाइम से बहुत बेहतर है।

हमारे पास अभी भी है @autoreleasepool{...}क्योंकि यह किसी भी नियम को नहीं तोड़ता है, हम स्वतंत्र हैं / हमारे पूल को सूखा देते हैं जब भी हमें इसकी आवश्यकता होती है :)।


1
एआरसी संदर्भ गिनती जीसी है, जावास्क्रिप्ट और जावा में आपके जैसे जीसी मार्क-एंड-स्वीप नहीं, लेकिन यह निश्चित रूप से कचरा संग्रह है। यह प्रश्न को संबोधित नहीं करता है - "आप कर सकते हैं" "आपको क्यों करना चाहिए" के प्रश्न का उत्तर नहीं देता है। आपको नहीं करना चाहिए
ग्लेन मेनार्ड

3

ऐसा इसलिए है क्योंकि आपको अभी भी संकेत के साथ संकलक प्रदान करने की आवश्यकता है जब यह ऑटोरेल्ड ऑब्जेक्ट्स के दायरे से बाहर जाने के लिए सुरक्षित है।


क्या आप मुझे इसका उदाहरण दे सकते हैं, जब आपको ऐसा करने की आवश्यकता होगी?
mk12


इसलिए एआरसी से पहले, उदाहरण के लिए, मेरे पास सीवीडीप्लेलिंक था जो मेरे ओपनगेल ऐप के लिए एक माध्यमिक थ्रेड पर चल रहा था, लेकिन मैंने इसके रनअप में एक ऑटोरेलिज पूल नहीं बनाया था क्योंकि मुझे पता था कि मैं कुछ भी नहीं कर रहा था (या पुस्तकालयों का उपयोग करके)। क्या इसका मतलब यह है कि अब मुझे जोड़ने की आवश्यकता है @autoreleasepoolक्योंकि मुझे नहीं पता कि क्या एआरसी कुछ को ऑटोरिलिज़ करने का निर्णय ले सकता है?
mk12

@ Mk12 - नहीं। आपके पास हमेशा एक ऑटो रिलीज़ पूल होगा जो हर बार मुख्य रन लूप के साथ निकल जाता है। आपको केवल एक जोड़ने की आवश्यकता है जब आप यह सुनिश्चित करना चाहते हैं कि जिन वस्तुओं को ऑटोरेल्ड किया गया है, वे अन्यथा पहले सूखा हो जाएंगे - उदाहरण के लिए, अगली बार रन लूप को गोल करना।
मटजग्लौय

2
@DougW - मैंने इस बात पर ध्यान दिया कि संकलक वास्तव में क्या कर रहा है और यहाँ इसके बारे में ब्लॉग किया गया है - iphone.galloway.me.uk/2012/02/a-look-under-arcs-hood- –-epHTML-3 /। उम्मीद है कि संकलन-समय और रन-टाइम दोनों पर क्या चल रहा है।
१०:५० पर मटजग्लौ

2

Https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html से उद्धृत :

ऑटोरेलिज पूल ब्लॉक और थ्रेड्स

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

यदि आपका आवेदन या धागा लंबे समय तक जीवित रहता है और संभावित रूप से बहुत सारे ऑटोरेल्ड ऑब्जेक्ट उत्पन्न करता है, तो आपको ऑटोरेलिज़ पूल ब्लॉकों (जैसे एपकिट और यूआईकिट मुख्य धागे पर करना) का उपयोग करना चाहिए; अन्यथा, ऑटोरेल्ड ऑब्जेक्ट जमा हो जाते हैं और आपकी मेमोरी फ़ुटप्रिंट बढ़ती है। यदि आपका अलग किया गया धागा कोको कॉल नहीं करता है, तो आपको ऑटोरेलिज़ पूल ब्लॉक का उपयोग करने की आवश्यकता नहीं है।

नोट: यदि आप NSThread के बजाय POSIX थ्रेड API का उपयोग करके द्वितीयक थ्रेड बनाते हैं, तो आप कोको का उपयोग नहीं कर सकते जब तक कि कोको मल्टीथ्रेडिंग मोड में न हो। कोको अपनी पहली NSThread ऑब्जेक्ट का पता लगाने के बाद ही मल्टीथ्रेडिंग मोड में प्रवेश करता है। सेकेंडरी पोसिक्स थ्रेड्स पर कोको का उपयोग करने के लिए, आपके एप्लिकेशन को पहले कम से कम एक NSThread ऑब्जेक्ट को अलग करना होगा, जो तुरंत बाहर निकल सकता है। आप परीक्षण कर सकते हैं कि क्या NSThread क्लास पद्धति के साथ कोको मल्टीथ्रेडिंग मोड में है, MultiThreaded।

...

ऑटोमैटिक रेफरेंस काउंटिंग या एआरसी में, सिस्टम MRR के रूप में एक ही रेफरेंस काउंटिंग सिस्टम का उपयोग करता है, लेकिन यह कंपाइल-टाइम पर आपको उपयुक्त मैमोरी मैनेजमेंट मेथड callforhe लगाता है। आपको नई परियोजनाओं के लिए एआरसी का उपयोग करने के लिए दृढ़ता से प्रोत्साहित किया जाता है। यदि आप एआरसी का उपयोग करते हैं, तो आमतौर पर इस दस्तावेज़ में वर्णित अंतर्निहित कार्यान्वयन को समझने की आवश्यकता नहीं है, हालांकि यह कुछ स्थितियों में सहायक हो सकता है। ARC के बारे में अधिक जानकारी के लिए, ARC रिलीज़ नोट्स में संक्रमण देखें।


2

एक विधि से नव निर्मित वस्तुओं को वापस करने के लिए ऑटोरेलिज पूल की आवश्यकता होती है। उदाहरण के लिए इस कोड के टुकड़े पर विचार करें:

- (NSString *)messageOfTheDay {
    return [[NSString alloc] initWithFormat:@"Hello %@!", self.username];
}

विधि में बनाई गई स्ट्रिंग में एक की एक बरकरार गणना होगी। अब कौन रिलीज के साथ गिनती बनाए रखेगा?

विधि ही? संभव नहीं है, इसे बनाई गई वस्तु को वापस करना है, इसलिए इसे लौटने से पहले इसे जारी नहीं करना चाहिए।

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

यदि फोन करने वाले को हमेशा कन्वेंशन द्वारा सभी लौटी हुई वस्तु को जारी करना होता है, तो नई बनाई गई प्रत्येक वस्तु को हमेशा इसे एक विधि से वापस करने से पहले बरकरार नहीं रखना होगा और इसे स्कोलर द्वारा तब तक जारी करना होगा, जब तक कि यह दायरे से बाहर न हो जाए यह फिर से लौटा है। यह कई मामलों में अत्यधिक अक्षम होगा क्योंकि एक व्यक्ति पूरी तरह से कई मामलों में रिटेन काउंट को बदलने से बच सकता है यदि कॉलर हमेशा लौटी हुई वस्तु को जारी नहीं करेगा।

यही कारण है कि ऑटोरेलिज पूल हैं, इसलिए पहली विधि वास्तव में बन जाएगी

- (NSString *)messageOfTheDay {
    NSString * res = [[NSString alloc] initWithFormat:@"Hello %@!", self.username];
    return [res autorelease];
}

autoreleaseकिसी ऑब्जेक्ट पर कॉल करने से यह ऑटोरेलिज़ पूल में जुड़ जाता है, लेकिन ऑटोरलीज़ पूल में ऑब्जेक्ट को जोड़ने का वास्तव में क्या मतलब है? ठीक है, इसका मतलब है कि आपके सिस्टम को " मैं चाहता हूं कि आप मेरे लिए उस वस्तु को जारी करें, लेकिन कुछ समय बाद, अभी नहीं, इसकी एक प्रतिधारण संख्या है जिसे रिलीज से संतुलित करने की आवश्यकता है अन्यथा स्मृति रिसाव होगी लेकिन मैं खुद ऐसा नहीं कर सकता अभी मुझे अपने मौजूदा दायरे से परे रहने के लिए वस्तु की आवश्यकता है और मेरा कॉलर मेरे लिए ऐसा नहीं करेगा, उसे इस बात की कोई जानकारी नहीं है कि यह करने की आवश्यकता है। इसलिए इसे अपने पूल में जोड़ें और एक बार जब आप इसे साफ कर लें। पूल, मेरे लिए मेरी वस्तु को भी साफ करें। "

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

इस एआरसी कोड पर विचार करें:

// Callee
- (SomeObject *)getSomeObject {
    return [[SomeObject alloc] init];
}

// Caller
SomeObject * obj = [self getSomeObject];
[obj doStuff];

कोड जो सिस्टम उत्पन्न करता है, वह या तो निम्न कोड की तरह व्यवहार कर सकता है (वह सुरक्षित संस्करण है जो आपको एआरसी और गैर-एआरसी कोड को स्वतंत्र रूप से मिलाने की अनुमति देता है):

// Callee
- (SomeObject *)getSomeObject {
    return [[[SomeObject alloc] init] autorelease];
}

// Caller
SomeObject * obj = [[self getSomeObject] retain];
[obj doStuff];
[obj release];

(ध्यान दें कि कॉलर में जारी / जारी करना केवल एक रक्षात्मक सुरक्षा बनाए रखना है, इसकी कड़ाई से आवश्यकता नहीं है, कोड इसके बिना पूरी तरह से सही होगा)

या यह इस कोड की तरह व्यवहार कर सकता है, जब दोनों को रनटाइम पर ARC का उपयोग करने का पता चलता है:

// Callee
- (SomeObject *)getSomeObject {
    return [[SomeObject alloc] init];
}

// Caller
SomeObject * obj = [self getSomeObject];
[obj doStuff];
[obj release];

जैसा कि आप देख सकते हैं, ऐप्पल ने एटॉर्लीज को समाप्त कर दिया है, इस प्रकार पूल को नष्ट होने पर विलंबित ऑब्जेक्ट रिलीज़, साथ ही साथ सुरक्षा बरकरार रहती है। यह कैसे संभव है और क्या वास्तव में पर्दे के पीछे चल रहा है, इसके बारे में अधिक जानने के लिए, इस इस ब्लॉग पोस्ट को देखें।

अब वास्तविक प्रश्न के लिए: कोई क्यों उपयोग करेगा @autoreleasepool ?

अधिकांश डेवलपर्स के लिए, उनके कोड में इस निर्माण का उपयोग करने के लिए आज केवल एक ही कारण बचा है और वह यह है कि जहां लागू हो वहां मेमोरी फुटप्रिंट को छोटा रखें। जैसे इस लूप पर विचार करें:

for (int i = 0; i < 1000000; i++) {
    // ... code ...
    TempObject * to = [TempObject tempObjectForData:...];
    // ... do something with to ...
}

मान लें कि हर कॉल tempObjectForDataएक नया बना सकता हैTempObject जिसे ऑटोरेलिज़ वापस किया जाता है। फॉर-लूप इन अस्थायी वस्तुओं में से एक मिलियन का निर्माण करेगा जो सभी वर्तमान ऑटोरेलिस्पुल में एकत्र किए जाते हैं और केवल एक बार उस पूल को नष्ट कर दिया जाता है, सभी टेम्प ऑब्जेक्ट्स भी नष्ट हो जाते हैं। जब तक ऐसा नहीं होता, तब तक आपके पास स्मृति में इन अस्थायी वस्तुओं में से एक मिलियन हैं।

यदि आप इसके बजाय इस तरह कोड लिखते हैं:

for (int i = 0; i < 1000000; i++) @autoreleasepool {
    // ... code ...
    TempObject * to = [TempObject tempObjectForData:...];
    // ... do something with to ...
}

फिर एक नया पूल हर बार फॉर-लूप चलता है और प्रत्येक लूप पुनरावृत्ति के अंत में नष्ट हो जाता है। लूप के एक लाख बार चलने के बावजूद किसी भी समय मेमोरी में लगभग एक ही अस्थायी ऑब्जेक्ट लटका हुआ है।

अतीत में आपको अक्सर थ्रेड का प्रबंधन करते समय स्वयं को ऑटोरेलिस्पुलस भी प्रबंधित करना पड़ता था (उदाहरण के लिए NSThread) केवल मुख्य धागे के रूप में एक कोको / यूकीट ऐप के लिए ऑटोरेलिज पूल होता है। फिर भी यह आज बहुत अधिक विरासत है क्योंकि आज आप शायद शुरू करने के लिए धागे का उपयोग नहीं करेंगे। आप GCD DispatchQueueके या NSOperationQueueइन दोनों का उपयोग करेंगे और ये दोनों आपके लिए एक शीर्ष स्तर के ऑटोरेलिज़ पूल का प्रबंधन करेंगे, जो एक ब्लॉक / कार्य को चलाने से पहले बनाया गया था और एक बार इसके साथ नष्ट हो गया था।


-4

इस विषय पर बहुत भ्रम होने लगता है (और कम से कम 80 लोग जो शायद अब इस बारे में भ्रमित हैं और सोचते हैं कि उन्हें अपने कोड के आसपास @autoreleasepool छिड़कना होगा)।

यदि कोई प्रोजेक्ट (इसकी निर्भरता सहित) विशेष रूप से एआरसी का उपयोग करता है, तो @autoreleasepool को कभी भी उपयोग करने की आवश्यकता नहीं है और यह कुछ भी उपयोगी नहीं करेगा। एआरसी सही समय पर वस्तुओं को जारी करने से निपटेगा। उदाहरण के लिए:

@interface Testing: NSObject
+ (void) test;
@end

@implementation Testing
- (void) dealloc { NSLog(@"dealloc"); }

+ (void) test
{
    while(true) NSLog(@"p = %p", [Testing new]);
}
@end

प्रदर्शित करता है:

p = 0x17696f80
dealloc
p = 0x17570a90
dealloc

मान के दायरे से बाहर जाते ही, प्रत्येक परीक्षण वस्तु को हटा दिया जाता है, बिना ऑटोरिएल पूल के बाहर निकलने का इंतजार किए बिना। (NSNumber उदाहरण के साथ भी यही बात होती है; यह हमें डीललोक का निरीक्षण करने की अनुमति देता है।) ARC ऑटोरेलिज़ का उपयोग नहीं करता है।

कारण @autoreleasepool को अभी भी मिश्रित एआरसी और गैर-एआरसी परियोजनाओं के लिए अनुमति है, जिन्होंने अभी तक एआरसी को पूरी तरह से संक्रमित नहीं किया है।

यदि आप गैर-एआरसी कोड में कॉल करते हैं, तो यह ऑटोरेलिज्ड ऑब्जेक्ट को वापस कर सकता है। उस स्थिति में, उपरोक्त लूप रिसाव होगा, क्योंकि वर्तमान ऑटोरेलिज पूल कभी भी बाहर नहीं निकलेगा। यहीं आप कोड ब्लॉक के आसपास @autoreleasepool डालना चाहते हैं।

लेकिन अगर आपने पूरी तरह से एआरसी संक्रमण कर लिया है, तो ऑटोरेलिज़पूल के बारे में भूल जाएं।


4
यह उत्तर गलत है और एआरसी प्रलेखन के खिलाफ भी है। आपके साक्ष्य एक महत्वपूर्ण बात है क्योंकि आप एक आवंटन पद्धति का उपयोग करते हुए होते हैं जो संकलक ऑटोरेलिज़ को नहीं करने का निर्णय लेता है। यदि आप अपने कस्टम वर्ग के लिए एक नया स्थैतिक आरंभक बनाते हैं तो आप इसे आसानी से काम नहीं कर सकते। यह इनिशियलाइज़र बनाएँ और इसे अपने लूप में उपयोग करें + (Testing *) testing { return [Testing new] }:। फिर आप देखेंगे कि डीललॉक को बाद में आने तक बुलाया नहीं जाएगा। यह तय है अगर आप एक @autoreleasepoolब्लॉक में लूप के अंदर लपेटते हैं ।
दिमा

@Dima iOS10 पर ट्रायल किया गया, डीललोक को ऑब्जेक्ट एड्रेस को प्रिंट करने के तुरंत बाद कॉल किया जाता है। + (Testing *) testing { return [Testing new];} + (void) test { while(true) NSLog(@"p = %p", [self testing]);}
KudoCC

@ कुडसीसी - तो क्या मैंने, और मैंने वही व्यवहार देखा जो आपने किया था। लेकिन, जब मैंने [UIImage imageWithData]समीकरण में फेंक दिया , तब, अचानक, मैंने पारंपरिक autoreleaseव्यवहार को देखना शुरू कर दिया , जिसमें @autoreleasepoolकुछ उचित स्तर तक शिखर स्मृति रखने की आवश्यकता थी।
रोब

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