Transitioning to ARC Release Notesहमें __block चर को शून्य में क्यों सेट करना है?
उपयोग लाइफटाइम क्वालिफायर से मजबूत संदर्भ साइकिल
आप मजबूत संदर्भ चक्र से बचने के लिए जीवन भर क्वालिफायर का उपयोग कर सकते से बचें। उदाहरण के लिए, आमतौर पर यदि आपके पास अभिभावक-बाल पदानुक्रम में व्यवस्थित वस्तुओं का आलेख है और माता-पिता को अपने बच्चों और को इसके विपरीत संदर्भित करने की आवश्यकता है, तो आप माता-पिता से बच्चे के रिश्ते को मजबूत बनाते हैं और बच्चे से माता-पिता का रिश्ता कमजोर अन्य स्थितियां अधिक सूक्ष्म हो सकती हैं, खासकर जब उनमें ब्लॉक ऑब्जेक्ट्स शामिल होते हैं।
मैन्युअल संदर्भ गणना मोड में,
__block id x;
को बनाए रखने का प्रभाव नहीं है। एआरसी मोड में,__block id x;
x
को बनाए रखने के लिए डिफ़ॉल्ट (केवल अन्य सभी मानों की तरह)। मैन्युअल संदर्भ गिनती मोड एआरसी के तहत व्यवहार प्राप्त करने के लिए, आप__unsafe_unretained __block id x;
का उपयोग कर सकते हैं। नाम__unsafe_unretained
का तात्पर्य है, हालांकि गैर-बनाए रखा चर खतरनाक है (क्योंकि यह लटक सकता है) और इसलिए निराश है। दो बेहतर विकल्प या तो__weak
का उपयोग करना है (यदि आपको आईओएस 4 या ओएस एक्स v10.6 का समर्थन करने की आवश्यकता नहीं है), या__block
मान को बनाए रखने के चक्र को तोड़ने के लिएnil
पर सेट करें।
ठीक है, तो __block
चर के बारे में क्या अलग है?
क्यों nil
पर सेट क्यों करें? __block
चर दो बार बनाए रखा है? सभी संदर्भ कौन रखता है? खंड? ढेर? ढेर? सूत्र? क्या?
निम्नलिखित कोड खंड इस समस्या को एक पैटर्न का उपयोग करके दिखाता है जिसे कभी-कभी मैन्युअल संदर्भ गणना में उपयोग किया जाता है।
MyViewController *myController = [[MyViewController alloc] init…];
// ...
myController.completionHandler = ^(NSInteger result) {
[myController dismissViewControllerAnimated:YES completion:nil];
};
[self presentViewController:myController animated:YES completion:^{
[myController release];
}];
के रूप में वर्णित है, बजाय, आप एक __block
क्वालीफायर का उपयोग करें और पूरा होने हैंडलर में nil
को myController चर सेट कर सकते हैं:
MyViewController * __block myController = [[MyViewController alloc] init…]; //Why use __block. my controller is not changed at all
// ...
myController.completionHandler = ^(NSInteger result) {
[myController dismissViewControllerAnimated:YES completion:nil];
myController = nil; //Why set to nil here? Is __block variable retained twice? Who hold all the reference? The block? The heap? The stack? The thread? The what?
};
भी क्यों myController
संकलक द्वारा nil
पर सेट नहीं है। हमें ऐसा क्यों करना है? ऐसा लगता है कि जब संकलक समाप्त हो जाता है तो मेरे नियंत्रक को फिर से उपयोग नहीं किया जाएगा जब संकलक प्रकार का पता चल जाएगा।
"लेकिन ब्लॉक स्वयं ऑब्जेक्ट को भी बनाए रखेगा क्योंकि इसे ब्लॉक के भीतर से दृढ़ता से संदर्भित किया जाता है।" क्यूं कर? बंद। –
__block जोड़ने से कैसे कोई फर्क पड़ता है? –
जब कोई ब्लॉक किसी ऑब्जेक्ट-सी ऑब्जेक्ट में पॉइंटर को कैप्चर करता है, तब तक उस ऑब्जेक्ट को तब तक बनाए रखा जाएगा जब तक आप '__weak' या '__unsafe_unretained' (या गैर-एआरसी कोड में' __block') का उपयोग न करें। –