Reputation: 8303
I'm using this code from within the connectionDidFinishLoading:connection
NSURLConnection asynchronous delegate method while downloading a large chunk of data.
- (void)saveCompatibilities:(NSArray *)objects {
//setup tempMoc
UIApplication *app = [UIApplication sharedApplication];
AppDelegate *appDelegate = (AppDelegate *)app.delegate;
NSManagedObjectContext *moc = appDelegate.managedObjectContext;
NSPersistentStoreCoordinator *storeCoordinator = moc.persistentStoreCoordinator;
NSManagedObjectContext *tempMoc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
tempMoc.persistentStoreCoordinator = storeCoordinator;
NSString *entityName = NSStringFromClass([Compatibility class]);
for (NSDictionary *newObjectDict in objects) {
[tempMoc performBlock:^{
Compatibility *object = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:tempMoc];
object.prod1 = newObjectDict[@"prod1"];
object.prod2 = newObjectDict[@"prod2"];
object.prod3 = newObjectDict[@"prod3"];
object.region = newObjectDict[@"region"];
object.result = newObjectDict[@"result"];
NSLog(@"%@", object);
}];
}
//do some other stuff here ...
tempMoc = nil;
}
This code runs ok and saves some objects, but crashes in the middle with this error:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '+entityForName: could not locate an NSManagedObjectModel for entity name 'Compatibility''
I set break points up and learned that the last line tempMoc = nil;
is being hit after saving some of the objects, but doesn't leave the function. It simply goes back into the loop and because tempMoc
is nil now, the error occurs.
Why doesn't it finish looping through the array of objects? And it it does leave the loop why doesn't it leave the function all together? I'm assuming it's due to multi-threading, which I'm new to.
Upvotes: 0
Views: 1137
Reputation: 3616
It is because of multi threading. performBlock will be called at some later time on a different thread possibly after method is done. Which means after tempMoc is set to nil. I think you should put the for loop inside the peformBlock like so
[tempMoc performBlock:^{
for (NSDictionary *newObjectDict in objects) {
Compatibility *object = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:tempMoc];
object.prod1 = newObjectDict[@"prod1"];
object.prod2 = newObjectDict[@"prod2"];
object.prod3 = newObjectDict[@"prod3"];
object.region = newObjectDict[@"region"];
object.result = newObjectDict[@"result"];
NSLog(@"%@", object);
}
}];
I don't think you need to set tempMoc to nil in the end.
Upvotes: 2