2013-02-25 2 views
0

Я преобразовал свой проект в ARC, и когда я достиг некоторых подклассов NSOperation, ответственных за загрузку некоторых изображений в фоновом режиме, код начал сбой.NSManagedObject crashing on NSOperation (ARC)

Так у меня NSOperation подкласса и его основной код:

- (void)main 
{ 
    Post *p = [[Post alloc] initWithNewManagedObjectContext]; 
    Post *post = (Post *)[p findById:postId]; 
    [post downloadAndProcessImageOfTypeThumbOrAll:thumbOrAll]; 

    if (![self isCancelled]) { 
     [target performSelectorOnMainThread:afterCompletionAction withObject:postId waitUntilDone:NO]; 
    } 
} 

код работает при компиляции без ARC (и с соответствующими выпусками), но когда он преобразуется в АРК он получил EXC_BAD_ACCESS Исключение сразу после завершения основного метода.

Я думаю, что это связано с ARC, выпуская любой объект, прежде чем он должен, возможно, объекты Posts. Но я не знаю, как сохранить их дольше.

Кроме того, [[Post alloc] initWithNewManagedObjectContext]; создает или повторно использует существующий контекст для доступа к объекту из CoreData.

Любые подсказки?

+1

Run инструментов с 'NSZombiesEnabled'. Это очень помогает в решении этих проблем. – borrrden

+0

Что такое цель? Вы держите ссылку на нее? Если у вас нет сильной ссылки, он будет немедленно освобожден, прежде чем 'executeSelectorOnMainThread:' может запускаться ... Это означает, что вы будете отправлять сообщение на освобожденный объект. – nielsbot

+0

'post' также будет освобожден, если у вас нет ссылки на него в другом месте. – nielsbot

ответ

0

Собственно, друг помог мне найти проблему. Благодаря каждому комментарию.

Проблема была с NSManagedObjectContext, к которому обращался фоновый поток.

Решение создало новый контекст для фонового потока, а используемый трюк хранит контекст на threadDictionary для доступа к другим фоновым потокам, если это необходимо.

Так что теперь, то [[Post alloc] initWithNewManagedObjectContext]; создает отдельный контекст:

NSManagedObjectContext *managedObjectContext = nil; 
NSThread *thread = [NSThread currentThread]; 
managedObjectContext = [[thread threadDictionary] valueForKey:@"managedObjectContext"]; 

if (!managedObjectContext) { 
    GTCoreData *gtcd = [[GTCoreData alloc] init]; 
    NSPersistentStoreCoordinator *coordinator = [gtcd persistentStoreCoordinator]; 
    if (coordinator != nil) { 
     managedObjectContext = [[NSManagedObjectContext alloc] init]; 
     [managedObjectContext setPersistentStoreCoordinator:coordinator]; 
     [[thread threadDictionary] setValue:managedObjectContext forKey:@"managedObjectContext"]; 
    } 
} 

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Post" inManagedObjectContext:managedObjectContext]; 
Post *post = [[Post alloc] initWithEntity:entity insertIntoManagedObjectContext:managedObjectContext]; 
return post;