I'm getting random crashes when creating an inferred mapping model (with Core Data's lightweight migration) within my application. By the way, I have to do it programmatically in my application while it is running.
This is how I create this model (after I have made proper currentModel and newModel objects, of course):
NSMappingModel *mappingModel = [NSMappingModel inferredMappingModelForSourceModel:currentModel destinationModel:newModel error:&error];
The problem is this: This method is crashing randomly. When it works, it works just fine without issues. But when it crashes, it crashes my application (instead of returning nil to signify that the method failed, as it should). By randomly, I mean that sometimes it happens and sometimes not. It is unpredictable.
Now, here is the deal: I'm running this method in another thread. More precisely, it is located inside a block that is passed via GCD to run on the global main queue. I need to do this for my UI to appear crisp to the user, i.e. so that I can display a progress indicator while the work is underway.
The strange thing seems to be that if I remove the GCD stuff and just let it run on the main thread, it seems to be working fine and never crashing. Thus, could it be because I'm running this on a different thread that this is crashing?
I somehow find that weird because I don't believe I'm breaking any Core Data rules regarding multi-threading. In particular, I'm not passing any managed objects around, and whenever I need access to the MOC, I create a new MOC, i.e. I'm not relying on any MOC (or for that matter: anything) that has been created earlier on the main thread. Besides the little MOC stuff that occurs, occurs after the mapping model creatio开发者_JS百科n method, i.e. after the point at which the app crashes, so it can't possibly be a cause of the crashes under consideration here.
All I'm doing is taking two MOMs and asking for a mapping model between them. That can't be wrong even under threading, now can it?
Any ideas on what could be going on?
First, what is the crash?
Second, Core Data generally is a single threaded API. There are things you can do in multiple threads but creating a NSMappingModel
is most likely not one of them. Why must you create the mapping model dynamically? If the MOMs are a known quantity then the mapping can be a known quantity as well.
update
First, the threading issue. Core Data is meant to be single threaded. However, the NSManagedObjectContext
knows how to lock the NSPersistentStoreCoordinator
correctly therefore you can have one NSManagedObjectContext
per thread because they know how to lock correctly. However this is not the case when you are working with and creating a mapping model.
However, the error you provided is not a Core Data error per se. That error indicates that somewhere in your code you are trying to stick a nil into a set. Without seeing the code that is generating the mapping model though it is difficult to guess as to exactly where.
Have you put a breakpoint at objc_throw_exception and see what line in your code is causing this crash? If it is in something non-obvious then I would suggest there is some point in your building of the mapping model that is giving Core Data an unexpected nil.
One thing you can try is locking the NSPersistentStore
and/or the NSManagedObjectContext
yourself to see if that resolves the crash. However I suspect when you do that you are going to again deal with performance issues.
I ended up giving up on this problem altogether and just created the damned mapping models myself.
精彩评论