2012-01-10 13 views
5

Mike Ash has written this introduction to ARC जहां वह कुछ इस तरह प्रस्तुत करता है:एआरसी का उपयोग करते हुए मैं कब और क्यों स्थानीय चर को __weak घोषित करना चाहता हूं?

__weak Foo *_weakFoo = [object foo]; 

क्यों मुझे क्या करना है कि एक स्थानीय, अस्थायी चर के लिए चाहेगा? __weak एक शून्य संदर्भ है जो संदर्भित ऑब्जेक्ट को हटा दिए जाने पर _weakFoo पॉइंटर स्वचालित रूप से शून्य पर सेट करेगा। इसके अलावा, __weak आईओएस में ही उपलब्ध है> = 5.

जब मैं बस इस ?:

Foo *_weakFoo = [object foo]; 

यह हमेशा एक वस्तु या नहीं के बराबर लौटने की उम्मीद है कर जब मैं मुसीबत में पड़ जाएगा।

Foo *_weakFoo = [object foo]; 
[self doSomethingStupid]; // does something bad so foo gets deallocated 
[_weakFoo doIt]; // CRASH! msg sent to deallocated instance 0x123456 

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

तो स्थानीय चर के लिए __weak कब समझ जाएगा, और मुझे कहीं और पागल चीज़ क्या करना चाहिए ताकि मुझे वास्तव में इसकी आवश्यकता हो?

उत्तर

9

मैं __weak स्थानीय चर का उपयोग करता हूं यदि मुझे एक बनाए रखने चक्र से बचने के लिए ब्लॉक के अंदर self में हेरफेर करना है। इस उदाहरण पर विचार करें जहां मैं एक स्ट्रिंग के लिए नेटवर्क अनुरोध करने के लिए जीसीडी और ब्लॉक का उपयोग कर रहा हूं, और फिर कक्षा द्वारा घोषित लेबल पर इसे सेट कर रहा हूं, इस मामले में, TurtlesViewController

__weak TurtlesViewController *weakSelf = self; 
dispatch_queue_t networkQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

dispatch_async(networkQueue, ^{ 

    // Kick off a network task for some data that is going to populate a label declared on our class 
    NSString *returnString = [networkDataSource retrieveTurtleTime]; 

    // Dispatch back to the main thread to populate the UILabel 
    dispatch_async(dispatch_get_main_queue(), ^{ 

     // Using self.label here creates a retain cycle. Self owns the block and the block has captured self 
     self.label.text = returnString; 

     // Instead, we use weakSelf for our reference to the label as it will be torn down by ARC at the end of the loop. 
     weakSelf.label.text = returnString; 
    }); 
}); 
+1

हालांकि एक सतत चक्र कैसे हो सकता है? – openfrog

+1

@openfrog - यह विशेष ब्लॉक एक सतत चक्र होने का सबसे बड़ा जोखिम नहीं हो सकता है, लेकिन जो मैंने चलाया है वह अधिसूचनाओं के लिए ब्लॉक-आधारित पर्यवेक्षक होगा (NSNotificationCenter के '-addObserverForName का उपयोग करके: ऑब्जेक्ट: कतार: उपयोगब्लॉक: ')। यदि आप किसी ऑब्जेक्ट में ऐसे पर्यवेक्षक को सेट करते हैं, और 'self' पर कुछ का संदर्भ लें, तो आप एक चक्र स्थापित करेंगे क्योंकि ऑब्जेक्ट ब्लॉक पर है और ब्लॉक ऑब्जेक्ट पर रखता है। –

+2

इसे लिखने के बाद मुझे एहसास हुआ कि यह सबसे अच्छा उदाहरण नहीं है क्योंकि dispatch_async() ब्लॉक की प्रतिलिपि बनाता है, लेकिन केवल विधि के अंत तक। एक बेहतर उदाहरण एनएसब्लॉकऑपरेशन का उपयोग कर रहा होगा क्योंकि ऑब्जेक्ट के जीवनकाल के लिए पारित ब्लॉक के इस तरह के उदाहरण के बाद, चक्रों को और अधिक बनाए रखने की संभावना है। –