2011-08-31 12 views
17

मैं एक fellow StackOverflow user है कि मैं जब एक संपत्ति को रिहा गेटर विधि का उपयोग नहीं करना चाहिए ने कहा था:उद्देश्य-सी में संपत्ति जारी करने के लिए मुझे गेटर का उपयोग क्यों नहीं करना चाहिए?

@property(nonatmic, retain) Type* variable; 
@synthesize variable; 

// wrong 
[self.variable release]; 

// right 
[variable release]; 

उन्होंने विस्तार से समझाने क्यों नहीं किया। वे मेरे लिए समान दिखाई देते हैं। My iOS book ने कहा कि एक संपत्ति पर गेटर इस तरह दिखेगा:

- (id)variable { 
    return variable; 
} 

तो यह मतलब यह नहीं है [self variable], self.variable, और variable सभी एक ही कर रहे हैं?

+0

यह एक बहुत ही खतरनाक सिफारिश है; गेटर हमेशा ऐसा नहीं लगेगा। असल में, अगर वह एक 'परमाणु' संपत्ति थी तो वह/-autorelease होगा। – bbum

उत्तर

4

एक ठेठ गेटर अधिक इस तरह दिखेगा ऑब्जेक्ट को आवश्यकतानुसार बाद में रिलीज़ किया जाना चाहिए (जब ऑटोरेलीज पूल निकाला जाता है)।

आमतौर पर, आप या तो self.variable = nil जो लाभ यह भी nil को चर (झूलने संकेत की वजह से दुर्घटनाओं से बचने), या [variable release] जो सबसे तेज है और यदि आपके सेटर अधिक एक dealloc विधि में उपयुक्त हो सकता सेट करता है का प्रयोग करेंगे कस्टम तर्क है।

9

आप वैकल्पिक रूप से कस्टम गेटर व्यवहार लिख सकते हैं, जिसके परिणामस्वरूप पूरी तरह से अलग व्यवहार हो सकता है। तो, आप हमेशा यह नहीं मान सकते कि [variable release] के समान परिणाम [self.variable release] हैं।

साथ ही, आप कस्टम गुण एक विशेष इवर बिना उन्हें समर्थन लिख सकते हैं ... यह गंदा तेजी से प्राप्त कर सकते हैं यदि आप ही टिककर खेल द्वारा लौटाए गए संदर्भों से वस्तुओं को रिहा शुरू!

self.variable = nil; 

इस का प्रभाव पड़ता है:

वहाँ अतिरिक्त कारण है कि मैं के बारे में पता कर रहा हूँ ...

+0

यह सच है, लेकिन मैं छवि नहीं कर सकता कि किस प्रकार का गेटर संपत्ति को बदल देगा जिस तरह से उपयोगकर्ता इसे रिलीज़ नहीं कर पाएगा।) – Eimantas

+1

@Eimantas: हालांकि, मैं कह सकता हूं कि आप ऑब्जेक्ट्स जारी नहीं कर रहे हैं आपके डेलोक में गेटर्स ... कस्टम गेटटर में लिखे गए कोड अन्य आइवरों तक पहुंचने का प्रयास कर सकते हैं जो पहले ही रिलीज़ हो चुके हैं, जिसके परिणामस्वरूप क्रैश हो रहा है। या ऐसे अन्य अजीब मामलों! – MechEthan

+3

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

13

कोई कस्टम एक्सेसर के साथ एक बनाए रखा संपत्ति के लिए हो सकता है, आप द्वारा वस्तु जारी कर सकते हैं ivar को सेट करना (जिसे 'चर' कहा जा सकता है यदि आपने केवल गुण घोषित किए हैं) पिछले मान को शून्य और जारी करने के लिए।

जैसा कि अन्य ने इंगित किया है, या तो सीधे ivar (यदि उपलब्ध हो) जारी कर रहा है या उपर्युक्त विधि का उपयोग कर रहा है ठीक है - आपको क्या नहीं करना चाहिए एक गेटर से लौटाए गए चर पर कॉल रिलीज है। तो

- (id)variable { 
    return [[variable retain] autorelease]; 
} 

अगर आप का उपयोग [self.variable release] आप एक अतिरिक्त retain और autorelease तुम सच में की जरूरत नहीं है कि जब आप सिर्फ वस्तु और उस कारण को रिहा करना चाहते हैं:

+0

मुझे पता था कि मैं अपने जवाब में कुछ महत्वपूर्ण भूल गया हूं ... तुम्हारा उत्साहित है क्योंकि यह समझने की एक महत्वपूर्ण बात है! – MechEthan

+0

मैंने [एकाधिक स्थानों] में पढ़ा है (http://stackoverflow.com/questions/5737312/set-to-nil-in-viewdidunload-but-release-in-dealloc/5737438#5737438) कि गुण ' dealloc' और 'viewDidUnload' में शून्य करने के लिए सेट। – JoJo

+1

यदि आपके पास एक ivar भी है, तो आप इसे सीधे जारी कर सकते हैं। मुद्दा यह है कि आप गेटटर से जो भी लौटाया जाता है उसे रिहा नहीं कर सकते क्योंकि यह असली अंतर्निहित चर होने की गारंटी नहीं है। सीधे ivar को रिहा करने से सेटर में किसी भी कस्टम तर्क को रोक दिया जाता है, यदि आपके पास कोई नहीं है, तो इससे कोई फर्क नहीं पड़ता है। – jrturton

4

नहीं सब ही टिककर खेल इस रूप ले:

- (id)variable { return variable; } 

... कि केवल सबसे आदिम रूप है। अकेले गुणों को और संयोजनों का सुझाव देना चाहिए, जो कार्यान्वयन को बदलते हैं। उपरोक्त आदिम अभिगमकर्ता स्मृति प्रबंधन, परमाणुता, या प्रतिलिपि अर्थशास्त्र के संयोजन के साथ उपयोग की जाने वाली मुहावरों के लिए जिम्मेदार नहीं है। subclass ओवरराइड में कार्यान्वयन भी नाजुक है।

कुछ वाकई संक्षिप्त उदाहरणों का पालन करें; वास्तविक कार्यक्रमों में चीजें स्पष्ट रूप से अधिक जटिल हो जाती हैं जहां कार्यान्वयन काफी जटिल हो जाते हैं।

1) गेटर उदाहरण चर वापस नहीं कर सकते।कई संभावनाओं में से एक:

- (NSObject *)a { return [[a copy] autorelease]; } 

2) सेटटर आवृत्ति चर को बनाए रख सकता है। कई संभावनाओं में से एक:

- (void)setA:(NSObject *)arg 
{ 
    ... 
    a = [arg copy]; 
    ... 
} 

3) यदि आप अपने कार्यक्रम है, जो यह मुश्किल बनाए रखने के लिए बनाता है के दौरान स्मृति प्रबंधन कार्यान्वयन के साथ खत्म। वर्ग के अर्थ विज्ञान (और कैसे यह उदाहरण चर 'रेफरी गिनती संभालती है) वर्ग के लिए रखा जाना चाहिए, और अपेक्षित परिणाम के लिए सम्मेलनों का पालन करें:

- (void)stuff:(NSString *)arg 
{ 
    const bool TheRightWay = false; 
    if (TheRightWay) { 
     NSMutableString * string = [arg mutableCopy]; 
     [string appendString:@"2"]; 
     self.a = string; 
     [string release]; 
     // - or - 
     NSMutableString * string = [[arg mutableCopy] autorelase]; 
     [string appendString:@"2"]; 
     self.a = string; 
    } 
    else { 
     NSMutableString * string = [arg mutableCopy]; 
     [string appendString:@"2"]; 
     self.a = string; 
     [self.a release]; 
    } 
} 

इन सरल नियमों का पालन करने में नाकाम रहने के लिए अपने कोड बनाए रखने के लिए कठिन बना देता है और विस्तार करने के लिए डीबग और दर्दनाक।

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

यह लेखकों/उप-वर्गों/ग्राहकों को यह भी उम्मीद करता है कि वर्ग कैसे सम्मेलन से विचलित हो जाता है, जो मूर्खतापूर्ण और समय उठने पर समय लेने वाली है और मुद्दों के उठने पर आपको सभी आंतरिक विवरण जारी करना होगा (वे किसी बिंदु पर)।

वे कुछ छोटे उदाहरण हैं कि संपत्ति के परिणामस्वरूप कॉलिंग रिलीज कैसे समस्याएं पेश करता है। कई वास्तविक दुनिया की समस्याएं बहुत कमजोर हैं और उन्हें ढूंढना मुश्किल है।

संबंधित मुद्दे