2015-04-16 1 views
0

С момента обновления до XCode 6.3 и iOS 8.3 Я получаю новую ошибку в своем приложении при объединении NSManagedObjectContexts (MOC) из фона в основной поток MOC.Crasher Core Data с ошибкой «dying managedobjectcontext», когда

В моей архитектуре есть основной MOC основного потока и создается несколько фоновых MOC для других потоков, которые являются временными и используются только для синхронизации новых данных сервера. Когда эти фоновые MOC сохраняются, я слушаю уведомление NSManagedObjectContextDidSaveNotification в основном потоке и звоните mergeChangesFromContextDidSaveNotification на основной MOC.

Это относится к документации по потоку с данными сердечника (см. Core Data Concurrency).

Это работало хорошо, но это обновление начало врезаться с этой ошибкой, которую я не могу проследить обратно к определенной строке моего кода:

illegally invoked -perform* on dying NSManagedObjectContext at: 
    (
    0 CoreData       0x28a2f273 <redacted> + 118 
    1 CoreData       0x28a32f09 <redacted> + 192 
    2 CoreFoundation      0x28c64e09 <redacted> + 12 
    3 CoreFoundation      0x28bbf515 _CFXNotificationPost + 1784 
    4 Foundation       0x29920749 <redacted> + 72 
    5 Foundation       0x2992522f <redacted> + 30 
    6 Foundation       0x29986a93 <redacted> + 98 
    7 Foundation       0x299867f7 <redacted> + 82 
    8 Foundation       0x299dfbd5 <redacted> + 408 
    9 CoreFoundation      0x28c72fed <redacted> + 20 
    10 CoreFoundation      0x28c706ab <redacted> + 278 
    11 CoreFoundation      0x28c709ff <redacted> + 734 
    12 CoreFoundation      0x28bbd201 CFRunLoopRunSpecific + 476 
    13 CoreFoundation      0x28bbd013 CFRunLoopRunInMode + 106 
    14 GraphicsServices     0x30359201 GSEventRunModal + 136 
    15 UIKit        0x2c361a59 UIApplicationMain + 1440 
    16 MyAppName       0x000c95a7 main + 170 
    17 libdyld.dylib      0x376c1aaf <redacted> + 2 
) 

Я превратился в зомби на XCode, ищет освобожденные контексты, но не нашел. Основной поток-слушатель, который вызывает слияние выглядит следующим образом:

- (void)coreDataDidSaveNotification:(NSNotification *)notification { 
    NSManagedObjectContext *savedContext = (NSManagedObjectContext *)notification.object; 

    if (savedContext != self.mainManagedObjectContext) { 
     __weak typeof(self) weakSelf = self; 
     [self.dispatch dispatchOnMainThread:^{ 
      NSLog(@"before merge"); 
      [weakSelf.mainManagedObjectContext mergeChangesFromContextDidSaveNotification:notification]; 
      NSLog(@"after merge"); 
     }]; 
    } 
} 

сообщение журнала «после слияния» вызывается перед тем авария случается, что дополнительное заблуждение. Я проверил keepCount на фоновом контексте в уведомлении, и он всегда больше нуля, когда вызывается слияние, поэтому он не освобождается в этой точке.

Любая идея, что происходит?

+0

Счет сохранения никогда не может быть равен нулю. Вы не можете использовать счетчик удержания, чтобы определить, был ли объект удален. – bbum

ответ

2

После долгих исследований я обнаружил, что фоновые контексты действительно освобождаются до завершения слияния. Если я сохраню ссылки на них, авария никогда не произойдет.

Похоже, что метод mergeChangesFromContextDidSaveNotification изменился. Уведомление, содержащее контекст, было достаточно, чтобы сохранить его до завершения слияния.

Я считаю, что сейчас происходит в том, что mergeChangesFromContextDidSaveNotification Теперь метод внутренне имеет слабую ссылку, и внутренне рассылает слияние в главном потоке снова, enqueueing для следующего цикла выполнения, поэтому я вижу журнал «после слияния» происходит до сбоя. К тому моменту, когда слияние действительно выполняется в следующем цикле запуска, я выпустил ссылку на фоновый MOC, и уведомление было выпущено, когда оно вышло за пределы области видимости, и поскольку внутренняя ссылка, скорее всего, теперь имеет слабый фон MOC был освобожден.

Смежные вопросы