2011-10-25 10 views
12

otrzymuję następujący błąd w mojej aplikacji:Rdzeń danych: stwierdzenie jest nadal aktywny

CoreData: error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. statement is still active with userInfo (null)

Wszystko, co mogę znaleźć zdaje się wskazywać, że mogą być problemy wielowątkowości z zarządzanym moje podstawowe dane obiektu kontekście, ale nie mogę znaleźć nigdzie w mojej aplikacji, gdzie by to miało miejsce. Uzyskuję dostęp do kontekstu zarządzanego obiektu i zarządzam nim w wątku tła. Kontekst tylko pobiera i manipuluje obiektami na tym jednym wątku tła. Po wykryciu zapisów do tego kontekstu za pomocą NSManagedObjectContextObjectsDidSaveNotification, scalam zmiany w innym kontekście, do którego mam dostęp tylko w głównym wątku. Kiedy wykonam połączenie scalające zmiany, błąd zostanie zgłoszony. Bardzo rzadko zdarza się to, nawet przy tych samych zestawach danych.

Czytałem gdzieś, że można "włączyć wielostronne asercje" za pomocą "-com.apple.CoreData.ThreadingDebug 3", ale nie byłem w stanie sprawić, żeby to działało. Czy ktoś wie, czy jest to możliwe? Miałem nadzieję, że to może włączyć pewne twierdzenia, które pomogłyby mi znaleźć miejsce, w którym gram z kontekstem na niewłaściwej nici lub czymś podobnym.

Jakieś inne wskazówki na temat tego, co może się dziać lub jak śledzić tego typu problemy?

+1

czy moja odpowiedź pomogła? –

+0

Przeczytałeś to w [TN2124: Mac OS X Debugging Magic] (https://developer.apple.com/library/ios/#technotes/tn2004/tn2124.html#SECCOREDATA). Kluczowy klucz to "Ta funkcja wymaga wariantu debugowania frameworka." Jeśli miałbyś ten wariant, możesz ustawić zmienną środowiskową 'DYLD_IMAGE_SUFFIX = _debug' i załadowałaby ona' CoreData_debug' zamiast 'CoreData' dla frameworka. Niestety, te warianty wydają się istnieć tylko dla OS X 10.5.x. :( –

Odpowiedz

13

Miałem podobny problem i znalazłem sposób, aby go rozwiązać.

Utworzono mechanizm tworzenia różnych kontekstów na podstawie nazw wątków (1 wątek = 1 kontekst).

#include <pthread.h> 
... 

    mach_port_t threadID = pthread_mach_thread_np(pthread_self()); 
    NSString *threadName = [NSString stringWithFormat:@"%x", threadID]; 
    NSManagedObjectContext *context = [singleton.threadsContexts objectForKey:threadName]; 
    if (!context) { 
     NSLog(@"Creating managed context for thread named '%@'", threadName); 
     context = [[NSManagedObjectContext alloc] init]; 
     [context setPersistentStoreCoordinator:[singleton.managedObjectContext persistentStoreCoordinator]]; 

     //initialize dictionary in your singleton if it as not been yet 
     if(!singleton.threadsContexts) 
     { 
      singleton.threadsContexts = [NSMutableDictionary new]; 
     } 
     [singleton.threadsContexts setObject:context forKey:threadName]; 
    } 

    return result; 

a potem, kiedy potrzebują pełnej wersji zarządzanego obiektu w wątku tła, mam kopię obiektu poświęconej tym wątku:

NSManagedObjectModel *myNewObject = [myBackgroundContext objectWithID:[myObject objectID]]; 

nadzieję, że ta odpowiedź pomoże.

+1

[[NSThread currentThread] name] zwraca "" dla mnie na iOS 7. [Ta odpowiedź] (http://stackoverflow.com/a/15523049/1571490) dał mi poprawny String. Poza tym działało bezbłędnie i wygląda na to, że wszystkie moje problemy z rdzeniem danych są naprawione Dziękuję! – fifarunnerr

+0

Działa świetnie! Nie widziałem mojej awarii od czasu użycia tego kodu! Musiałem również użyć techniki fifa, aby uzyskać nazwę wątku. Nie zapomnij zainicjować NSMutableDictionary w swoim singletonie ... Biegałem trochę w kółko, aż zdałem sobie sprawę, że :: DUH :: – RyanG

+1

To jest dość stara odpowiedź i dla nowszych projektów używam Magical Record, który ma wbudowany -w obsłudze wielowątkowych danych podstawowych.Jedna dokumentacja nie jest wspaniała, ale oszczędza dużo czasu, gdy wiesz, jak korzystać z tej biblioteki. https://github.com/magicalpanda/MagicalRecord –