12

I am getting the following error in my app:

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)

Everything that I can find seems to indicate the I may be having multi-threading issues with my core data managed object context, but I can't seem to find anywhere in my app where this would be the case. I am accessing and managing a managed object context on a background thread. The context is only fetching and manipulating objects on that one background thread. When I detect saves to that context through NSManagedObjectContextObjectsDidSaveNotification, I am merging the changes into a different context that I only access on my main thread. When I make the call to merge the changes, the error is thrown. It is very rare that this occurs, even with the same data sets.

I read somewhere that it is possible to 'enable multi-threading assertions' using '-com.apple.CoreData.ThreadingDebug 3', but I haven't been able to get this to work. Does anyone know if this is possible? I was hoping this might turn on some assertions that would help me find where I am playing with the context on the wrong thread or something.

Any other clues on what might be happening or how to track this sort of problem down?

Peter DeWeese
  • 18,141
  • 8
  • 79
  • 101
toofah
  • 4,455
  • 4
  • 31
  • 42
  • You read that in [TN2124: Mac OS X Debugging Magic](https://developer.apple.com/library/ios/#technotes/tn2004/tn2124.html#SECCOREDATA). The key bit is, "This feature requires the debug variant of the framework." If you had that variant, you could set the environment variable `DYLD_IMAGE_SUFFIX=_debug` and it would load `CoreData_debug` rather than `CoreData` for the framework. Unfortunately, those variants seem to only exist for OS X 10.5.x. :( – Jeremy W. Sherman Jan 29 '13 at 05:52

1 Answers1

13

I had a similar problem and found a way to solve it.

I've created a mechanism creating different contexts based on thread names (1 thread = 1 context).

#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;

and then, when i need a full version of a managed object in a background thread, I get a copy of the object dedicated to this thread :

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

Hope this answer will help.

RyanG
  • 4,393
  • 2
  • 39
  • 64
Mick F
  • 7,312
  • 6
  • 51
  • 98
  • 1
    [[NSThread currentThread] name] returns "" for me on iOS 7. [This answer](http://stackoverflow.com/a/15523049/1571490) gave me a correct String. Besided that, it worked flawlessly and looks like all my Core Data threading issues are fixed. Thanks! – fifarunnerr Feb 20 '14 at 15:29
  • Works great! I have not seen my crash since I have been using this code! I also had to use fifa's technique to get the thread name. Another tip, don't forget to initialize the NSMutableDictionary in your singleton... I ran around in circles a bit till I realized that ::DUH:: – RyanG Feb 21 '14 at 15:37
  • 1
    This is quite an old answer and for newer projects, I'm using Magical Record which has a built-in support for multi-threading core data. The documentation is not great but it saves a lot of time once you know how to use this lib. https://github.com/magicalpanda/MagicalRecord – Mick F Feb 24 '14 at 16:19