6

के साथ ऑब्जेक्ट संदर्भों पर __block कीवर्ड का उपयोग कब करें I समझते हैं कि __block ब्लॉक के लिए स्केलर चर पर स्टोरेज प्रकार की आवश्यकता है ताकि उन्हें अपडेट देखने के लिए, लेकिन ऑब्जेक्ट्स पर इसकी आवश्यकता हो? मेरा मानना ​​है कि __weak ब्लॉक के भीतर उपयोग किए जाने वाले स्वयं संदर्भ को कैप्चर करते समय उपयोग किया जाना चाहिए, लेकिन मुझे नहीं लगता कि वास्तव में __block सामान्य वस्तुओं के लिए संग्रहण प्रकार का उपयोग करना आवश्यक होगा।एआरसी

+0

भी [क्या __weak और __block के बीच का अंतर संदर्भ?] (http://stackoverflow.com/questions/11773342/what-the-difference-between-weak-and-block-reference) –

+0

मैं विशेष रूप से पूछ रहा हूं: जब '__block' संग्रहण प्रकार sh एआरसी का उपयोग करते समय गैर-स्केलर, गैर-स्व-ऑब्जेक्ट संदर्भों पर उपयोग किया जा सकता है? यदि वे अन्य लिंक उस प्रश्न का उत्तर देते हैं तो मैंने इसे याद किया है। – chinabuffet

+0

@chinabuffet: स्केलर प्रकारों और ऑब्जेक्ट पॉइंटर प्रकारों के लिए यह कैसे काम करता है इसके बीच कोई अंतर नहीं है। – newacct

उत्तर

15

__block स्केलर चर के लिए आवश्यक है यदि आप ब्लॉक के अंदर कोड के साथ अपना मूल्य बदलना चाहते हैं। ब्लॉक के अंदर कैप्चर किए गए स्केलर const के रूप में दिखाई देते हैं और इसलिए बदला नहीं जा सकता है। यदि आपके पास किसी ऑब्जेक्ट के लिए पॉइंटर है, तो वही भेद लागू होता है - कैप्चर पॉइंटर स्वयं const पॉइंटर होगा और इसलिए संशोधित नहीं किया जा सकता है, लेकिन ऑब्जेक्ट को इंगित किया जा सकता है कि ब्लॉक के अंदर कोड द्वारा संशोधित किया जा सकता है। यदि आप ऑब्जेक्ट को इंगित करना चाहते हैं, तो पॉइंटर को ही बदलना चाहिए, और इसलिए सूचक को __block प्रकार के साथ घोषित किया जाना चाहिए। ऑब्जेक्ट को __block के रूप में घोषित करना कभी भी आवश्यक नहीं है, बल्कि ऑब्जेक्ट के लिए केवल पॉइंटर, और केवल तभी सूचक को बदला जाना चाहिए।

यदि आपके पास सही मानसिक मॉडल है, तो ब्लॉक भ्रमित नहीं हैं। यह जानना महत्वपूर्ण है कि ब्लॉक को शुरुआत में ढेर पर आवंटित किया जाता है, और जब वैक्स फ्रेम को पॉप किया जाता है तो लेक्सिकल गुंजाइश नष्ट हो जाती है तो गायब हो जाती है। यदि आप ब्लॉक को उस लंबवत दायरे के जीवनकाल के आसपास लटकना चाहते हैं जिसमें ब्लॉक बनाया गया था, तो Block_copy() का उपयोग करके इसे ढेर में ले जाएं या इसे -copy संदेश भेज दें। जब ढेर में एक ब्लॉक की प्रतिलिपि बनाई जाती है, तो सभी कब्जे वाले const चर के साथ जाते हैं, और किसी भी ऑब्जेक्ट्स इन const वेरिएबल्स को बनाए रखा जाता है। जब ब्लॉक ढेर से हटा दिया जाता है, तो const चर द्वारा इंगित सभी ऑब्जेक्ट्स जारी किए जाते हैं।

__block चर "उन्नत" अविवेक की अतिरिक्त परत संकलक उपयोग करता है (और है कि आप नहीं दिख रहा है) ब्लॉक में शामिल है, इसलिए जब ब्लॉक ढेर में कॉपी किया जाता है, इसलिए __block चर कब्जा कर लिया है , और अदृश्य पॉइंटर्स इन __block चर के नए ढेर स्थान को इंगित करने के लिए समायोजित किए गए हैं। इसका मतलब है कि __block वैरिएबल का पता बदल सकता है, इसलिए यदि आप उस पते का उपयोग करते हैं तो सावधान रहें। आप यह भी देख सकते हैं कि __block कुछ अर्थों में ब्लॉक के बाहर परिवर्तनीय जीवन 'बाहर' है, इसलिए इन चरों को ब्लॉक से बाहर कोड से पढ़ और संशोधित किया जा सकता है।

मैं संक्षिप्त किया गया है, लेकिन आप बेहतर स्पष्टीकरण यहां पा सकते हैं, बढ़ती जटिलता में सूचीबद्ध:

http://ios-blog.co.uk/tutorials/programming-with-blocks-an-overview/

http://www.cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html

http://www.mikeash.com/pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html

+0

तो यदि ब्लॉक कहीं संदर्भ के रूप में पारित किया गया है, तो जो भी ब्लॉक को पैरामीटर के रूप में प्राप्त कर रहा है, उसे भविष्य में इसका उपयोग करने के लिए तुरंत ब्लॉक की प्रतिलिपि बनाने की आवश्यकता है? – chinabuffet

+0

यदि ब्लॉक संदर्भ लेक्सिकल स्कोप (स्टैक फ्रेम) को पार कर सकता है जिसमें ब्लॉक परिभाषित किया गया था, तो ब्लॉक ऑब्जेक्ट को ढेर में ले जाने के लिए इसकी प्रतिलिपि बनाई जानी चाहिए। मुझे लगता है कि निर्माण से रिमोट स्थानों पर होने वाली प्रतियां होने की तुलना में ब्लॉक बनाने के दौरान कॉपी करना सुरक्षित होगा। – Fred

0

वे फ़ंक्शन स्तर चर के लिए उपयोग किए जाते हैं। ये ब्लॉक (और संलग्न गुंजाइश) के भीतर उत्परिवर्तनीय हैं और यदि किसी भी संदर्भ ब्लॉक को ढेर में कॉपी किया गया है तो संरक्षित किया जाता है। __block स्टोरेज संशोधक के साथ घोषित संलग्न अक्षीय दायरे के लिए स्थानीय वैरिएबल संदर्भ द्वारा प्रदान किए जाते हैं और इसलिए उत्परिवर्तनीय होते हैं। किसी भी बदलाव को संलग्न लेक्सिकल गुंजाइश में प्रतिबिंबित किया जाता है, जिसमें समान संलग्न लेक्सिकल स्कोप के भीतर परिभाषित किसी भी अन्य ब्लॉक शामिल हैं।

__block वेरिएबल्स वेरिएबल के लेक्सिकल स्कोप के भीतर घोषित या बनाए गए सभी ब्लॉक और ब्लॉक प्रतियों के बीच साझा किए गए भंडारण में रहते हैं। इस प्रकार, भंडारण ढेर फ्रेम के विनाश से बच जाएगा यदि फ्रेम के भीतर घोषित ब्लॉक की कोई भी प्रति फ्रेम के अंत से परे जीवित रहती है (उदाहरण के लिए, बाद में निष्पादन के लिए कहीं भी लगाया जा रहा है)। इसलिए जब आप किसी ब्लॉक के भीतर ऑब्जेक्ट को संशोधित करने की आवश्यकता होती है या जब आपको स्टैक फ्रेम के विनाश के बाद ऑब्जेक्ट की आवश्यकता होती है तो उनका उपयोग करें।