मुझे वस्तुओं को कब जारी करना चाहिए - (शून्य) दृश्य-लोड के बजाय -dealloc में?


103

के -(void)viewDidUnloadलिए अच्छा क्या है ?

क्या मैं सिर्फ सब कुछ नहीं छोड़ सकता था -dealloc? यदि दृश्य अनलोड -deallocकिया जाता है, वैसे भी नहीं कहा जाएगा?

जवाबों:


51

पहले से ही जो संकेत दिया गया है, उसके अलावा, मैं तर्क के बारे में अधिक विस्तार से बताना चाहता था -viewDidUnload

इसे लागू करने के लिए सबसे महत्वपूर्ण कारणों में से एक यह है कि UIViewControllerउपवर्गों में आमतौर पर दृश्य पदानुक्रम में विभिन्न साक्षात्कारों के मालिक होते हैं। उदाहरण के लिए, इन गुणों को IBOutletsनिब से लोड करते समय या प्रोग्रामेटिक रूप से अंदर रखा जा सकता है -loadView

उपखंडों के अतिरिक्त स्वामित्व का UIViewControllerमतलब यह है कि जब इसका दृश्य पदानुक्रम से हटा दिया जाता है और स्मृति को बचाने के लिए भी जारी किया जाता है, जिसके माध्यम से उप-अवलोकन भी दृश्य द्वारा जारी किए जाते हैं, तो वे वास्तव में नहीं निपटाए जाएंगे क्योंकि UIViewControllerस्वयं के पास अभी भी अपना बकाया है उन वस्तुओं के संदर्भ को भी बनाए रखना। UIViewControllerइन वस्तुओं के अतिरिक्त स्वामित्व को जारी करना यह सुनिश्चित करता है कि उन्हें नि: शुल्क मेमोरी से मुक्त किया जाएगा।

आपके द्वारा यहां जारी की जाने वाली वस्तुओं को आमतौर पर फिर से बनाया जाता है और जब UIViewControllerदृश्य re-loadedएक निब से या कार्यान्वयन के माध्यम से फिर से सेट होता है -loadView

यह भी ध्यान दें कि UIViewController viewसंपत्ति nilउस समय तक है जब यह विधि कहलाती है।


1
आपको डेवलपर /apple.com/library/ios/#featuredarticles/… को पढ़ने / देखने के लिए नियंत्रक जीवन-चक्र को समझना चाहिए
पॉल सोल्ट

21

जैसा कि प्रलेखन कहता है :

इसे कम-मेमोरी स्थितियों के दौरान कहा जाता है, जब व्यू कंट्रोलर को अपने दृश्य को जारी करने की आवश्यकता होती है और मेमोरी को मुक्त करने के लिए उस दृश्य से जुड़ी कोई भी वस्तु।

उसी स्थिति deallocमें नहीं कहा जाता है। यह विधि केवल OS3 और इसके बाद के संस्करण में उपलब्ध है। IPhone ओएस 2.x में एक ही स्थिति से निपटना एक वास्तविक दर्द था!

अद्यतन जुलाई 2015 : यह ध्यान दिया जाना चाहिए कि viewDidUnloadआईओएस 6 में पदावनत किया गया था क्योंकि "दृश्य अब कम-मेमोरी स्थितियों के तहत शुद्ध नहीं होते हैं और इसलिए इस पद्धति को कभी नहीं बुलाया जाता है।" तो, आधुनिक सलाह इसके बारे में चिंता करने और उपयोग करने के लिए नहीं है dealloc


6
डॉक्स से भी: "आपको इसे केवल उन ऑब्जेक्ट्स के लिए करना चाहिए जिन्हें आप बाद में आसानी से या तो अपने व्यूडीडलॉड मेथड में या अपने एप्लिकेशन के अन्य हिस्सों से आसानी से रीक्रिएट कर सकते हैं। आपको इस विधि का उपयोग उपयोगकर्ता डेटा या कोई अन्य जानकारी जारी करने के लिए नहीं करना चाहिए जो कि नहीं कर सकते। आसानी से पुनर्जीवित ”। यह एक सवाल है जो मैंने खुद भी किया था, धन्यवाद!
लेओलोबेटो

यदि दृश्य वर्तमान में दिखाई दे रहा है तो क्या होगा? कम मेमोरी चेतावनी के कारण इसे छोड़ना बुरा नहीं होगा? ;) तो ऐप बस खाली खाली होगा। मुझे कम मेमोरी के कारण व्यू जारी करने की बात नहीं आती। अगर मुझे कोई दृश्य दिखाई नहीं देता है, तो मैं हमेशा पूरे नियंत्रक को छोड़ता हूं। Althogh मेरे पास एक रूट व्यू कंट्रोलर है जो बरकरार रहता है और सभी लोडिंग / अनलोडिंग का प्रबंधन करता है चाइल्ड व्यू कंट्रोलर्स ...
धन्यवाद

नहीं, यदि आप सिर्फ एक दृश्य को दूसरे के लिए स्वैप करते हैं तो आप इसका उपयोग नहीं करेंगे। उस मामले के बारे में सोचें जहां आपके पास UINavigationController के साथ विचारों का "स्टैक" है। केवल एक दृश्य दिखाई देता है और, यदि आपके पास स्मृति चेतावनी है, तो आप उन सभी को जारी कर सकते हैं जो दिखाई नहीं दे रहे हैं।
स्टीफन डार्लिंगटन

आप कैसे नियंत्रित करते हैं कि viewDidUnload को वर्तमान दृश्य दृश्य में नहीं कहा जाता है क्योंकि धन्यवाद ने नोट किया है?
एरियलकैमस

1
viewDidUnload को वर्तमान में दिखाई देने वाले दृश्य पर नहीं बुलाया जाएगा, केवल उन दृश्यों पर जो दृश्यमान नहीं हैं।
प्रातः

9

ऐसा इसलिए है क्योंकि आप आम तौर पर सेट के @propertyरूप "(nonatomic, retain)"में इस तरह के रूप में सेट करते हैं जो आपके लिए बनाया जाता है और वर्तमान ऑब्जेक्ट को जारी करता है और फिर तर्क को बरकरार रखता है अर्थात

self.property = nil;

... की तर्ज पर कुछ करता है:

[property release];
property = [nil retain];

इसलिए आप दो पक्षियों को एक पत्थर से मार रहे हैं: मेमोरी मैनेजमेंट (मौजूदा ऑब्जेक्ट को जारी करना) और पॉइंटर को एनआईएल को सौंपना (क्योंकि एनआईएल पॉइंटर पर कोई भी संदेश भेजने से एनआईएल वापस आ जाएगा)।

उम्मीद है की वो मदद करदे।


8

याद रखें कि viewDidUnloadदृश्य नियंत्रक में एक विधि है, दृश्य में नहीं। दृश्य की dealloc विधि जब दृश्य अनलोड कहा जाता हो जाएगा, लेकिन दृश्य नियंत्रक के dealloc विधि बाद में जब तक नहीं कहा जा सकता है।

यदि आपको कम स्मृति चेतावनी मिलती है और आपका दृश्य प्रदर्शित नहीं हो रहा है, जो कि किसी भी समय के लिए होगा, तो आप UIImagePickerController का उपयोग करते हुए उपयोगकर्ता को चित्र लेने देंगे, आपका दृश्य अनलोड हो जाएगा और इसके बाद पुनः लोड करने की आवश्यकता होगी।


यह समझ आता है। अगर मैं हमेशा पूरे व्यू कंट्रोलर को छोड़ दूं तो क्या होगा? यही मैं वास्तव में करता हूं। इस मामले में मुझे -व्यूडीड यूलोड, बहुत कुछ नहीं करना है? मेरे पास कभी भी ऐसी स्थिति नहीं थी जहां मैं केवल दृश्य छोड़ दूं, क्योंकि मैं हमेशा पूरे कंट्रोलर को छोड़ देता हूं अगर यह दृश्यमान नहीं है।
धन्यवाद

ठीक है, बस याद रखें कि ऐसे मामले में जहां आपका दृष्टिकोण दिखाई दे रहा है, लेकिन आपके पास इसके ऊपर ImagePicker जैसा एक पूर्णस्क्रीन दृश्य है, आपका दृश्य अनलोड हो सकता है, भले ही आपने इसके लिए योजना नहीं बनाई हो।
डेविड मेय्यूड्स

6

निष्कर्ष:

देखें नियंत्रकों के पास एक दृश्य संपत्ति है। आमतौर पर एक निब या कोड का टुकड़ा इस दृश्य में अन्य विचार जोड़ता है। यह अक्सर इस तरह के -viewDidLoad विधि के अंदर होता है:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self createManyViewsAndAddThemToSelfDotView];
}

इसके अलावा, एक निब फ़ाइल एक बटन बना सकती है और इसे दृश्य नियंत्रक के दृश्य में जोड़ सकती है।

IPhone OS 2.2 पर, जब -didReceiveMemoryWarning सिस्टम से मंगवाया गया था, तो आपको मेमोरी खाली करने के लिए कुछ जारी करना था। आप पूरे दृश्य नियंत्रक के दृश्य को जारी कर सकते हैं यदि यह समझ में आता है। या इसमें केवल बड़ी मेमोरी-खपत वाली सामग्री।

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
    // Release anything that's not essential, such as cached data
}

अब, नए ओएस 3.0 में, एक -व्यूडिड्यूऑनलोड विधि है, जिसे सिस्टम से तब प्राप्त किया जाएगा जब कम मेमोरी के कारण दृश्य अनलोड किया गया हो (कृपया मुझे सही करें: जब वास्तव में यह कहा जाता है?)

-viewDidUnload का उपयोग उन सभी ऑब्जेक्ट्स को रिलीज़ करने के लिए किया जाता है जो व्यू कंट्रोलर और व्यू दोनों के स्वामित्व में थे। कारण: यदि कोई व्यू कंट्रोलर चिल्ड्रन्स ऑफ द व्यू यानी एक बटन के संदर्भ में रखता है, तो संदर्भित बच्चे के विचार जारी नहीं किए जाएंगे, क्योंकि उनकी रिटेन काउंट है> = = 1. जब वे इनव्यूडिड्यूऑनलोड जारी किए जाते हैं, तो वे मुक्त हो सकते हैं याद से।


1
ध्यान में रखते हुए रिमेबर ने स्व.बटन = निल करने के लिए अनलोड किया; नहीं [बटन रिलीज़];;
mk12

6

Apple ने दृश्य को हटा दिया गया है अब लोड करें, अब आप अपने objetcs को जारी करने के लिए doReceiveMemoryWarning या Dealloc का उपयोग करते हैं।

IOS 6 में, UIViewController के viewWillUnload और viewDidUnload विधियां अब हटा दी गई हैं। यदि आप डेटा जारी करने के लिए इन विधियों का उपयोग कर रहे थे, तो इसके बजाय didReiveiveMemoryWarning विधि का उपयोग करें। यदि आप उपयोग नहीं किए जा रहे हैं, तो आप इस विधि का उपयोग दृश्य नियंत्रक के दृश्य के संदर्भ को जारी करने के लिए भी कर सकते हैं। आपको यह परीक्षण करने की आवश्यकता होगी कि ऐसा करने से पहले दृश्य एक विंडो में नहीं है।


5

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


3

आप अपने द्वारा रखे गए किसी भी साक्षात्कार को जारी कर सकते हैं, उदाहरण के लिए कि UIImageView को आपने अपने loadView पद्धति में बनाए रखा है, या बेहतर है कि छवि उस UIImageView पर है।

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