2009-06-16 8 views
9

मैंने कोड (संभवतः ऐप्पल का अपना नमूना कोड) देखा है, जिस तरह से लिखा गया है, जहां यह ivar को डेलोक में रिलीज़ करता है और संपत्ति को डीडयूनललोड में सेट करता है।क्या इवर को छोड़ना और संश्लेषित ivar को एक ही समय में शून्य करना आवश्यक है?

उदा।

- (void)viewDidUnload 
{ 
    self.navigationController = nil; 
} 

- (void)dealloc 
{ 
    [_navigationController release]; 
} 

उन्हें दो स्थानों पर क्यों करें? इसके अलावा, एक में शून्य क्यों सेट करें और दूसरे में रिलीज़ करें। ऐसा लगता है कि self.property = nil केवल सबकुछ का ख्याल रखेगा क्योंकि यह रिलीज होगा और ivar को शून्य में सेट करेगा।

उत्तर

5

आप सही हैं: आप वास्तव में delloc सहित self.property = nil कर सकते हैं। केवल नकारात्मक बात यह है कि यदि सेटर विधि केवल ivar को रिलीज़ करने से कहीं अधिक जटिल है, तो आप पहले से जारी किए गए अन्य फ़ील्ड तक पहुंचने का प्रयास कर सकते हैं।

क्यों आप viewDidUnload में आउटलेट भी जारी करते हैं , यह एक स्मृति अनुकूलन है। चूंकि आप viewDidUnload में रिलीज की जाने वाली चीजें हैं जो दृश्य फिर से लोड होने पर पुनर्स्थापित किए जाएंगे, उन्हें छोड़कर कम स्मृति स्थितियों में स्मृति को मुक्त कर दिया जाएगा।

+0

धन्यवाद, उस मामले में viewDidUnload कोड वस्तु को रिहा करने के लिए dealloc रूप में एक ही कोड का इस्तेमाल किया जा सकता था इसलिए, यानी [_navigationController रिलीज] इसे शून्य करने के बजाय, सही है? – Boon

+1

हां, लेकिन नहीं। -dealloc को छोड़कर हर जगह एक्सेसर का प्रयोग करें। डैनियल ने दिए गए कारणों के लिए -डैलोक में एक्सेसर्स का उपयोग विवादास्पद है (ऐप्पल जो भी वे अनुशंसा करते हैं, उनके बारे में भी अस्पष्ट है)। बस अपने सभी बनाए गए ivars -dealloc में जारी करने की आदत में जाओ। अपने लिए ऐसा करने के लिए किसी अन्य चीज पर शर्त न लगाएं। और जब भी आप कुछ छोड़ते हैं, इसे शून्य पर सेट करें। ओबीजेसी का अधिकांश सुरक्षा नेट के बिना है; अच्छी आदतें आपके प्रोग्राम को काम करती रहती हैं क्योंकि संकलक आपको बचाएगा नहीं। (ठीक है, शायद क्लेंग अंततः हमें बचाएगा, लेकिन केवल इसकी शक्ति का उपयोग अच्छा होगा।) –

0

यदि आप कचरा संग्रह (उद्देश्य-सी 2.0 में उपलब्ध) पर भरोसा कर रहे हैं तो ivarnil पर सेट करना और release को कॉल करना एक ही अंत प्राप्त होगा।

मुझे लगता है कि आप जिस कोड को देख रहे हैं वह release के साथ मेमोरी का प्रबंधन कर रहा है और इसे केवल nil पर सेट कर रहा है ताकि आप बाद में उस ऑब्जेक्ट तक पहुंचने का प्रयास न करें जो अब नहीं है। जब आप जीसी पर भरोसा नहीं कर रहे हैं तो nil मेमोरी प्रबंधन की तुलना में अधिक बहीखाता है।

+0

काफी नहीं - - [एओबजेक्ट रिलीज] जीसी के तहत कुछ भी नहीं करेगा (यह एक एनओपी है), जबकि शून्य पर सेट कचरा कलेक्टर की अनुमति देगा अंततः ऑब्जेक्ट को मुक्त करने के लिए (यह एक संदर्भ को हटा रहा है), जब तक कि इवर को कमजोर संदर्भ के रूप में परिभाषित न किया जाए। – xtophyr

1

ऐप्पल पुनर्मूल्यांकन करता है कि आप इनिट और विशेष रूप से डीलोक रूटीन में सेटर्स नहीं कहते हैं।

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

इसलिए, आप सामान्य रूप से उपयोग करें: अपने init दिनचर्या में

_navigationController = [[NavController alloc] init]; 

शैली कोड, अपने dealloc में

[_navigationController release]; 

शैली कोड, और अन्य कोड में setters जहां किसी चीज़ का पूरी तरह से माना जाता है पूर्ण।

कुछ मामलों पर विचार करने के:

  • उपवर्ग setNavigationController ओवरराइड करता है और init द्वारा आवंटित अपनी ही ivars संदर्भ देता है। Init पर क्रैश।
  • सबक्लास ओवरराइड सेट अपविगेशन नियंत्रक और डीलोक में जारी अपने स्वयं के इवर्स का संदर्भ देता है। Dealloc पर क्रैश।
  • सबक्लास सेट नेविगेशन नियंत्रक ओवरराइड करता है और स्क्रीन के कुछ हिस्सों को दोबारा हटा देता है। चक्र, या गड़बड़ प्रदर्शन के निर्बाध अपशिष्ट।
  • अन्य वस्तुओं एक ही समय में पुनः आवंटित की जाती किया जा रहा निरीक्षण navigationController और उन पर्यवेक्षकों dealloc
  • दौरान आग आदि
संबंधित मुद्दे