循环使用NSPrivateQueueConcurrencyType上下文将数据保存到Core Data会意外地离开循环

时间:2013-07-07 00:20:15

标签: ios objective-c multithreading core-data nsmanagedobjectcontext

在下载大量数据时,我在connectionDidFinishLoading:connection NSURLConnection异步委托方法中使用此代码。

- (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;
}

此代码运行正常并保存一些对象,但在此错误中间崩溃:

  

由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'+ entityForName:找不到实体名称的NSManagedObjectModel'兼容性''

我设置了断点并了解到在保存某些对象后,最后一行tempMoc = nil;被击中,但是没有离开该函数。它只是回到循环中,因为tempMoc现在为零,所以会发生错误。

为什么不完成循环遍历对象数组?它确实离开循环为什么不将功能全部放在一起?我假设它是由于多线程,我是新手。

1 个答案:

答案 0 :(得分:2)

这是因为多线程。稍后可能会在方法完成后在不同的线程上调用performBlock。这意味着在tempMoc设置为nil之后。我认为你应该将for循环放在peformBlock中,如此

        [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);
            }
        }];

我认为你最终不需要将tempMoc设置为nil。