5

के साथ dispatch_async का उपयोग करते समय EXC_BAD_ACCESS प्राप्त करना मेरे पास coredata में छवियां हैं जिन्हें मैं तालिका दृश्य के लिए आलसी लोड करने का प्रयास कर रहा हूं। प्रत्येक सेल उपलब्ध होने पर छवि को अपडेट करने के लिए संबंधित कोर डेटा इकाई के लिए पर्यवेक्षक का उपयोग करता है। इकाई में प्रासंगिक कोड इस प्रकार है:कोर डेटा

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    // The heavy lifting seems to be during firing of the fault and accessing data, 
    // so i'm trying to do that in the background thread. 
    UIImage *i = [UIImage imageWithData:self.imageEntity.data]; 
    // I now need to notify observers that the image is ready on the main thread 
    dispatch_async(dispatch_get_main_queue(), ^{ 
    [self willChangeValueForKey:@"image"]; 
    image = i; 
    [self didChangeValueForKey:@"image"]; 
    }); 
}); 

परियोजना एआरसी का उपयोग करता है, मैं किसी भी संकलक त्रुटि या चेतावनी नहीं मिल रहा है, और मैं जब मैं इसे एक तरह से जब तक मैं तेजी से स्क्रॉल काम करता है चलाने के लिए, और उसके बाद जब मैं i घोषित कर रहा हूं तो लाइन पर एक EXC_BAD_ACCESS।

मुझे यहां क्या याद आ रही है?

+0

क्या आपने 'NSZombieEnabled' के साथ प्रयास किया था? – zoul

+0

यदि आप dispatch_async का उपयोग नहीं कर रहे हैं तो क्या होगा? बस मुख्य धागे –

+0

पर चलाएं NSZombie मेरे लिए कोई अतिरिक्त प्रकाश नहीं डाला है। अगर मैं dispatch_async नहीं करता हूं तो यह मुख्य थ्रेड को अवरुद्ध कर देगा और वास्तव में खराब तरीके से स्क्रॉल करेगा। – dizy

उत्तर

7

स्पष्ट रूप से CoreData objects is not thread safe ला रहा है। तो यह एक ही persistentStoreCoordinator, लेकिन विभिन्न ऑब्जेक्ट कॉन्टैक्स का उपयोग करने का सुझाव दिया गया है। यहाँ मेरी अद्यतन कोड अब दुर्घटना लगता है कि है:

UIImage *i = [UIImage imageWithData:self.imageEntity.data]; 

autorelease के लिए निर्धारित है:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    @autoreleasepool { 
    // Create a new context 
    NSManagedObjectContext *backgroundContext = [[NSManagedObjectContext alloc] init]; 
    // Use an existing coordinator 
    NSPersistentStoreCoordinator *coordinator = [[DataSource sharedDataSource] persistentStoreCoordinator]; 
    [backgroundContext setPersistentStoreCoordinator:coordinator]; 
    // Getting objectID does not fire the fault, so we grab it but actually fetch the object 
    // on a background context to be thread safe. 
    Image *imageEntity = (Image*)[backgroundContext objectWithID:self.imageEntity.objectID]; 
    image = [UIImage imageWithData:imageEntity.data]; 
    // Notify observers that the image is ready on the main thread 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [self willChangeValueForKey:@"image"]; 
     [self didChangeValueForKey:@"image"]; 
    }); 
    } 
}); 
+0

क्या आप छवि प्रबंधित ऑब्जेक्ट संदर्भ में मुख्य थ्रेड पर छवि को सहेज सकते हैं? आप यह कैसे करेंगे, क्योंकि यह पृष्ठभूमि धागे पर बनाया गया था? – SAHM

1

Dizy, यह भी है कि कि कोड में बनाई गई है छवि वस्तु को ध्यान में रखना। Dispatch_async विधि मुख्य कतार पर चलती है, इसलिए एक मौका है कि छवि के लिए आवंटित स्मृति तब तक जारी की जा सकती है जब मुख्य धागा प्रेषण ब्लॉक चलाता है।

+0

अच्छा बिंदु, क्या मैं बस इसे हल करने के लिए @autoreleasepool {} में पूरी चीज़ लपेटता हूं? – dizy

+0

मैं बाहरी ब्लॉक में छवि को बनाए रखूंगा और फिर इसे आंतरिक ब्लॉक में छोड़ दूंगा। –

+0

मैं परियोजना – dizy

0

कोरडाटा थ्रेड सुरक्षित नहीं है, आपको क्रैश से बचने के लिए संदर्भ प्रबंधित करना होगा। यदि आप कोर डेटा में डेटा अपडेट करने के लिए बहुत सी समवर्ती प्रक्रियाओं का भारी उपयोग करने की योजना बना रहे हैं, तो मैं आपको MagicalRecord पर एक नज़र डालने का सुझाव दूंगा, जो रेल के सक्रिय रिकॉर्ड से प्रेरित एक अद्भुत पैटर्न है और यह इन सभी पहलुओं को वास्तव में स्मार्ट तरीके से संभालता है ।

+0

में एआरसी का उपयोग कर रहा हूं MagicalRecord को इंगित करने के लिए धन्यवाद, बहुत बढ़िया लगता है। – dizy