2009-04-29 10 views
11

उदाहरण:एक स्व-कार्यान्वित गेटर क्यों लौटाया जाना चाहिए और वापस लौटाया ऑब्जेक्ट?

- (NSString*) title { 
    return [[title retain] autorelease]; 
} 

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

उत्तर

12

यहाँ से http://www.macosxguru.net/article.php?story=20030713184140267

- (id)getMyInstance 
    { 
     return myInstanceVar ; 
    } 

या

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

क्या अंतर है? दूसरा एक कॉलर को एक कंटेनर ऑब्जेक्ट का इंस्टेंस वैरिएबल प्राप्त करने की अनुमति देता है, कंटेनर का निपटान करता है और आवृत्ति चर के अप्रत्यक्ष रूप से इंस्टेंस वैरिएबल के रिलीज से चोट पहुंचाने के बिना, वर्तमान ऑटोरेलेज्ड पूल की अगली रिलीज तक इंस्टेंस चर के साथ खेलना जारी रखता है अपने कंटेनर की रिहाई के द्वारा उत्पन्न:

aLocalVar = [aContainer getAnInstanceVar] ; 
[aContainer release]; 
doSomething(aLocalVar); 

"हो" पहले के रूप में कार्यान्वित किया जाता है, तो आप लिखना चाहिए:

aLocalVar = [[aContainer getAnInstanceVar] retain]; 
[aContainer release]; 
doSomething(aLocalVar); 
[aLovalVar release]; 

प्रथम रूप की अवधि में थोड़ा और अधिक कुशल है कोड निष्पादन गति। हालांकि, यदि आप दूसरों द्वारा उपयोग किए जाने वाले ढांचे को लिख रहे हैं, तो शायद दूसरे संस्करण की सिफारिश की जानी चाहिए: यह आपके ढांचे का उपयोग करने वाले लोगों के लिए जीवन को थोड़ा आसान बनाता है: उन्हें क्या करना है इसके बारे में बहुत कुछ नहीं सोचना है ... ;) यदि आप पहली शैली संस्करण चुनते हैं, तो इसे अपने दस्तावेज़ में स्पष्ट रूप से बताएं ... आप जिस भी तरीके से चयन करेंगे, याद रखें कि संस्करण 1 से संस्करण 2 में बदलना क्लाइंट कोड के लिए सहेजा जाता है, जब संस्करण 2 से संस्करण 1 में वापस जा रहा है मौजूदा क्लाइंट कोड तोड़ें ...

0

मैंने पहले इस पैटर्न को नहीं देखा है, लेकिन यह मेरे लिए काफी व्यर्थ लगता है। मुझे लगता है कि क्लाइंट कोड मूल ऑब्जेक्ट पर "रिलीज" कहता है तो वापस लौटाए गए मूल्य को सुरक्षित रखना है। यह वास्तव में कुछ भी चोट नहीं पहुंचाता है, लेकिन मुझे संदेह है कि स्थिति अच्छी तरह से डिजाइन की गई पुस्तकालयों में अक्सर होती है।


आह, ठीक है। दस्तावेज़ से जुड़े स्मोर्गन से, ऐसा लगता है कि यह अब उन तरीकों में से एक है जिसे ऐप्पल वर्तमान में सिफारिश कर रहा है कि लोग इसका उपयोग करें। मुझे लगता है कि मैं अभी भी पुराने स्कूल संस्करण पसंद करते हैं:

- (NSString *) value 
{ 
    return myValue; 
} 

- (void) setValue: (NSString *) newValue 
{ 
    if (newValue != myValue) 
    { 
     [myValue autorelease]; // actually, I nearly always use 'release' here 
     myValue = [newValue retain]; 
    } 
} 
+0

यह निर्भर करता है। उदाहरण के लिए, यह गुणों के लिए एक पूर्ण आवश्यकता है जिसे कई धागे से एक्सेस किया जा सकता है। आम तौर पर, ऐसी परिस्थितियां जो अक्सर नहीं आती हैं वे हैं जो वास्तव में कष्टप्रद सिर-स्क्रैचर्स का कारण बनती हैं। –

+0

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

+0

और बहु-थ्रेडेड एक्सेस के मामले में, मैं आमतौर पर [ओब्जे प्रतिलिपि] का उपयोग करता हूं - वस्तुओं के अलग-अलग उदाहरण होने से संघर्ष के किसी भी मौके को समाप्त कर दिया जाता है। –

7

यह सिर्फ उन मामलों में जहां किसी कंटेनर जारी करता है, के बाद से उस मामले में यह और भी स्पष्ट है कि वे खुद को वस्तु को बनाए रखने चाहिए के लिए नहीं है।

NSString* newValue = @"new"; 
NSString* oldValue = [foo someStringValue]; 
[foo setSomeStringValue:newValue]; 
// Go on to do something with oldValue 

यह उचित है, लेकिन अगर न सेटर है और न ही गेटर "कुछ करने के लिए पर जाओ" भाग autorelease का उपयोग करता है संभावना है, दुर्घटना होगा क्योंकि OLDVALUE अब पुनः आवंटित की जाती किया गया है (और कोई नहीं यह सोचते हैं बनाए रखा था: इस कोड पर विचार करें यह)। आप आमतौर पर Apple's accessor method examples से तकनीक 1 या तकनीक 2 का उपयोग करना चाहते हैं, इसलिए उपरोक्त की तरह कोड काम करेगा क्योंकि अधिकांश लोग अपेक्षा करेंगे।

3

इस

return [[title retain] autorelease]; // releases at end of current run loop (or if autorelease pool is drained earlier) 

दूसरा एक गारंटी देता है कि एक ग्राहक के साथ काम करने के लिए एक गैर dealloced वस्तु होगा के साथ इस कोड

return [[title retain] release]; // releases immediately 

की तुलना करें।

यह इस (क्लाइंट कोड) की तरह एक स्थिति में उपयोगी हो सकता है:

NSString *thing = [obj title]; 
[obj setTitle:nil]; // here you could hit retainCount 0! 
NSLog(@"Length %d", [thing length]); // here thing might be dealloced already! 

बनाए रखने (और autoreleaserelease के बजाय का उपयोग करते हैं) अपने title विधि में उड़ा से इस कोड को रोकता है। ऑटोरेलेज्ड ऑब्जेक्ट में release विधि नहीं होगी जब तक कि वर्तमान कॉल स्टैक निष्पादित नहीं किया जाता है (वर्तमान रन लूप का अंत)। यह सभी क्लाइंट कॉल कॉल में कोड को इस ऑब्जेक्ट का उपयोग करने के बारे में चिंता किए बिना इस मौके का उपयोग करने का मौका देता है।

याद रखने की महत्वपूर्ण बात: यह जावा, रूबी या PHP नहीं है। सिर्फ इसलिए कि आपके पास yer [sic] चर में किसी ऑब्जेक्ट का संदर्भ है, यह सुनिश्चित नहीं करता है कि आपको इसे आपके नीचे से नहीं हटाया जाएगा। आपको इसे बरकरार रखना है, लेकिन तो आपको इसे रिलीज़ करना याद रखना होगा। Autorelease आपको इससे बचने देता है। आपको हमेशा ऑटोोरलीज़ का उपयोग करना चाहिए जबतक कि आप कई पुनरावृत्तियों के साथ गुण या लूप से निपट नहीं रहे हैं (और शायद तब तक तब तक नहीं जब तक कोई समस्या न हो)।

+0

यहां मेरा प्रश्न भी देखें: http://stackoverflow.com/questions/3816898/methods-that-call-methods-basics-of-autorelease –