2011-06-15 13 views
8

मुझे एक ब्लॉक के बाहर से __block (ब्लॉक म्यूटेबल) चर का उपयोग करने का प्रयास करते समय एक अजीब समस्या का सामना करना पड़ रहा है जिसमें इसे संशोधित किया गया है। यह एक बहुत ही खिलौना उदाहरण है कि मैं सिर्फ सामान्य रूप में ब्लॉक के एक बेहतर समझ पाने के उपयोग कर रहा हूँ है, लेकिन वर्तमान में मुझे लगता है कि एक NSDictionary जो NSDictionary के enumerateKeysAndObjectsUsingBlock:Obj-C __block चर व्यवहार को बनाए रखने

का उपयोग करता है की सामग्री के साथ एक स्ट्रिंग बनाता है इस विधि के साथ एक नियंत्रक है
- (NSString*) contentsOfDictionary:(NSDictionary*)dictionary 
{ 
    __block NSString *content = @""; 

    [dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){ 
     NSString* contentToAppend = [NSString stringWithFormat:@"Object:%@ for key:%@\n", obj, key]; 
     content = [content stringByAppendingString:contentToAppend]; 
     NSLog(@"Content in block:\n%@", content); 
    }]; 

    NSLog(@"Content out of block:\n%@", content); 

    return content; 
} 

जब मैं एक शब्दकोश सामग्री युक्त के साथ इस विधि चलाएँ:

Value Key 
"Queen" "card" 
"Hearts" "suit" 
"10"  "value" 

content चर सही ढंग से ब्लॉक के भीतर संशोधित किया गया है और मैं एक यात्रा के साथ इस उत्पादन प्राप्त करें:

... ब्लॉक में सामग्री:

Object:Queen for key:card 

... ब्लॉक में सामग्री: कोड कदम के रूप में जैसे ही

Object:Queen for key:card 
Object:Hearts for key:suit 
Object:10 for key:value 

:

Object:Queen for key:card 
Object:Hearts for key:suit 

... ब्लॉक में सामग्री हालांकि ब्लॉक के बाहर, content स्ट्रिंग तक पहुंचने से EXC_BAD_ACCESS फेंकता है और एक रन अवसर पर ऐसा लगता है कि कुछ कचरा स्मृति मुद्रित हो सकती है (पुन: पेश नहीं कर सकती) ...

इस चर को जल्दी से हटाया जा रहा है? मैं इस धारणा के तहत था कि इसे __block परिभाषा देने का मतलब यह होगा कि ब्लॉक के दौरान उपयोग किए जाने पर इसे बनाए रखा जाता है और जब ब्लॉक निकलता है तब जारी किया जाता है - लेकिन चर को एक स्ट्रिंग अक्षर होने के कारण से शुरू करने के लिए बनाए रखा जाता है और इसलिए मैं अपेक्षा करता हूं इस विधि को जल्द से जल्द बाहर निकलने तक इसे तब तक नहीं हटाया जाना चाहिए।

उत्तर

15

यह आपकी समस्या है। इस ऑब्जेक्ट का पता content में संग्रहीत है। प्रत्येक इस (अंतर्निहित) लूप के माध्यम से जाता है - जो कहता है, प्रदान किए गए ब्लॉक का प्रत्येक आमंत्रण - एक नई वस्तु बना रहा है और फिर उस नई वस्तु का पता content पर असाइन कर रहा है। इनमें से कोई भी वस्तु इसके युक्त ऑटोरेलीज पूल से बाहर नहीं है।

आपको क्या करना चाहिए NSMutableString का उपयोग कर और म्यूटेबल स्ट्रिंग में contentToAppend को सीधे जोड़ना। उदाहरण के लिए:

- (NSString*) contentsOfDictionary:(NSDictionary*)dictionary 
{ 
    NSMutableString *content = [NSMutableString string]; 
    [dictionary enumerateKeysAndObjectsUsingBlock: 
    ^(id key, id obj, BOOL *stop){ 
     NSString* contentToAppend = [NSString stringWithFormat: 
      @"Object:%@ for key:%@\n", obj, key]; 
     [content appendString:contentToAppend]; 

     NSLog(@"Content in block:\n%@", content); 
    }]; 

    NSLog(@"Content out of block:\n%@", content); 
    return content; 
} 

ध्यान दें कि __block नहीं रह गया है, के लिए आवश्यक है के रूप में आप ब्लॉक के भीतर कहीं भी content को नहीं देते।

+0

हाँ। ऐसा करता है। – donalbain

5

आंतरिक रूप से, -enumerateKeysAndObjectsUsingBlock: एक ऑटोरेलीज पूल का उपयोग कर रहा है। __block स्कॉप्ड ऑब्जेक्ट्स ब्लॉक के जीवनकाल के अंत से पहले नहीं बनाए जाते हैं, इसलिए आप उस ब्लॉक के दायरे में बनाए गए ऑब्जेक्ट के साथ समाप्त होते हैं जिसे तब डीलोकेट किया जाता है जब डिक्शनरी के ऑटोोरिज़ पूल को निकाला जाता है, जो आपके मूल्य के प्रिंट को प्रिंट करने का प्रयास करने से पहले होता है content

content = [content stringByAppendingString:contentToAppend]; 

-stringByAppendingString: एक नया, autoreleased ऑब्जेक्ट:

+0

मैं डिक्शनरी के ऑटोरेलीज पूल को निकालने से कैसे रोक सकता हूं? क्या मैं कुछ कर रहा हूं इसके बारे में मूलभूत रूप से गलत है? – donalbain

+0

आप पूल को ओवरराइड नहीं कर सकते हैं, लेकिन आप ऑब्जेक्ट के भीतर ऑब्जेक्ट को बरकरार रख सकते हैं (सुनिश्चित करें कि ऑब्जेक्ट्स को रिसाव न करें!) और उसके बाद ऑटोरेलीज या लूप के बाहर इसे रिलीज़ करते समय इसे छोड़ दें। –

+0

मुझे लगता है कि, अंतर्निहित ऑटोरेलेज्ड स्ट्रिंग ByAppendingString को समस्या से बचने के लिए मैन्युअल रूप से बनाए रखा जा सकता है और जारी किया जा सकता है, लेकिन मुझे लगता है कि MutableString इसे बहुत आसान बनाता है। मुझे एहसास है कि यह मेरा आखिरी मेमोरी प्रबंधन संबंधित ब्लॉक मुद्दा नहीं होगा हालांकि :( – donalbain

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