5

테이블 뷰를 지연로드하려고하는 큐레 데이터에 이미지가 있습니다. 각 셀은 관련 핵심 데이터 엔티티에 대한 관찰자를 사용하여 이미지를 업데이트 할 때이를 업데이트합니다. 다음과 같이 기업에 대한 관련 코드는 다음과 같습니다핵심 데이터와 함께 dispatch_async를 사용할 때 EXC_BAD_ACCESS 가져 오기

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

이 프로젝트는 내가 어떤 컴파일러 오류 또는 경고를받지 못했습니다, ARC를 사용하고, 그때 내가 빠른 스크롤 할 때까지 가지 작동 실행하고 때 얻을 라인을 선언 할 때 EXC_BAD_ACCESS.

무엇이 여기에 있습니까?

+0

'NSZombieEnabled'를 시도 했습니까? – zoul

+0

dispatch_async를 사용하지 않으면 어떻게됩니까? 그냥 메인 스레드에서 실행 –

+0

NSZombie는 나를 위해 어떤 여분의 빛도 발산하지 않습니다. dispatch_async를하지 않으면 주 스레드를 차단하고 실제로 스크롤 할 수 없습니다. – dizy

답변

7

분명히 CoreData objects is not thread safe을 가져 오는 중입니다. 따라서 동일한 persistentStoreCoordinator를 사용하지만 다른 ObjectContext를 사용하는 것이 좋습니다. 여기에 더 이상 충돌이 보인다 내 업데이트 된 코드입니다 :

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

오토 릴리즈를 위해 설정됩니다

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

프로젝트에서 ARC를 사용하고 있습니다. – dizy

0

CoreData는 스레드로부터 안전하지 않으므로 충돌을 피하기 위해 컨텍스트를 관리해야합니다. 많은 동시 프로세스를 사용하여 핵심 데이터의 데이터를 업데이트하려는 경우 MagicalRecord을 살펴볼 것을 제안합니다. 이는 Active Record of Rails에서 영감을 얻은 놀라운 패턴으로,이 모든 측면을 매우 현명한 방식으로 처리합니다 .

+0

MagicalRecord를 지적 해 주셔서 감사합니다. 꽤 멋진 것 같습니다. – dizy

관련 문제