5

Tablo görünümü için tembel bir şekilde yüklemeye çalıştığım coredata resimlerim var. Her bir hücre, biri mevcut olduğunda görüntüyü güncellemek için ilgili çekirdek veri varlığı için bir gözlemci kullanır. aşağıdaki gibi varlıktaki ilgili kodudur:Çekirdek Verileri ile dispatch_async kullanılırken EXC_BAD_ACCESS öğesinin alınması

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"]; 
    }); 
}); 

proje herhangi derleyici hata veya uyarı almıyorum, ARC kullanır ve ben o zaman hızlı kaydırma kadar bu tür işleri çalıştırmak ve ne zaman almak i 'i ilan ettiğimde hat üzerindeki bir EXC_BAD_ACCESS.

Burada nelerin eksik?

+0

'NSZombieEnabled' ile denediniz mi? – zoul

+0

dispatch_async kullanmıyorsanız ne olur? sadece –

+0

NSZombie ana iş parçacığı üzerinde çalıştırmak benim için fazladan ışık tutmaz. Eğer dağınıklık yapmazsam, ana iş parçacığını engeller ve gerçekten zayıf ilerler. – dizy

cevap

7

Görünüşe göre CoreData objects is not thread safe getiriliyor. Bu yüzden aynı kalıcıStoreCoordinator'u kullanması önerilir, ancak farklı ObjectContexts. Burada artık çökmesine görünüyor benim güncellenen kod:

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

autorelease için ayarlanır:

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

Görüntüyü ana iş parçacığı üzerinde, uygulama yönetilen nesne bağlamında kaydeder misiniz? Bunu arka plan iş parçacığı üzerinde oluşturulduğundan nasıl yaparsınız? – SAHM

1

Dizy, ayrıca kodda oluşturulan görüntü nesnesi unutmayın. Dispatch_async yöntemi, ana sıra üzerinde çalışır, bu nedenle, ana iş parçacığı dağıtım bloğunu çalıştırdığı zaman, görüntü için tahsis edilen bellek serbest bırakılabilir.

+0

İyi nokta, bunu çözmek için bütün şeyi @autoreleasepool {} içine koydum mu? – dizy

+0

Görüntüyü dış blokta tutar, ardından iç blokta serbest bırakırdım. –

+0

Projede ARC kullanıyorum – dizy

0

CoreData iş parçacığı güvenli değildir, çökmeleri önlemek için bağlamları yönetmeniz gerekir. Core Data'daki verileri güncellemek için bir çok eşzamanlı süreç kullanmayı planlıyorsanız, Active Ray of Rails'den ilham alan ve tüm bu yönleri gerçekten akıllı bir şekilde ele alan MagicalRecord modeline göz atmanızı öneririm. .

+0

MagicalRecord'u işaretlediğiniz için çok güzel geliyor. – dizy

İlgili konular