我有一个使用Core Data的多线程应用。我在启动时遇到了很多崩溃,以及各种奇怪的错误消息。但是,有时它工作正常!我从未在自己的iPhone4上看到过崩溃,但它在其他设备上崩溃了。我想我已经找到了问题,但我不确定如何最好地解决它。
当应用程序启动时,我使用GCD从Web下载数据并在后台线程上更新核心数据。在主线程上,我继续设置表视图,其中一个命令触发NSManagedObjectContext
getter。我几乎使用标准模板代码,因此这是第一次运行时,通常的惰性实例代码会创建NSPersistentStoreCoordinator
。
然而,后台线程正在创建一个新的NSManagedObjectContext
供自己使用。这包括获取NSPersistentStoreCoordinator
如下:
// Create a new NSManagedObjectContext for this thread
NSManagedObjectContext *threadContext = nil;
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil)
{
threadContext = [[NSManagedObjectContext alloc] init];
[threadContext setPersistentStoreCoordinator:coordinator];
NSMergePolicy *mergePolicy = [[NSMergePolicy alloc] initWithMergeType:NSMergeByPropertyObjectTrumpMergePolicyType];
[threadContext setMergePolicy:mergePolicy];
} else {
NSLog(@"Error - No NSPersistentStoreCoordinator");
}
我90%肯定这个问题是两个线程同时进入NSPersistentStoreCoordinator
代码。两个线程都认为对象是nil
,因此创建对象。这导致第一个线程到达那里的问题,因为ivar突然指向错误的位置。那时坏事就发生了!
那么如何最好地解决这个问题呢?我通过向后台线程添加sleep(1)
暂时解决了这个问题:)但我不确定这是否是最好的解决方案!我已经尝试更改NSPersistentStoreCoordinator
属性,以便它们是原子的,但这没有帮助。我应该将@synchronise
中的每个标准getter包装到互斥锁中吗?我还没有时间尝试这个,但它应该停止两个线程运行相同的代码。或者有更好的方法吗?
思想?
谢谢克雷格
======================================
有关信息,以下是我看到的一些错误和崩溃。这些都是随机的,但它可能会帮助其他人在将来找到这篇文章。
2012-01-18 22:19:57.586 CBF [10468:11d03] - [NSSQLModel _addPersistentStore:identifier:]:无法识别的选择器发送到实例0x6b80390
2012-01-18 22:19:57.595 CBF [10468:11d03] * 终止应用程序 未捕获的异常'NSInvalidArgumentException',原因:' - [NSSQLModel _addPersistentStore:identifier:]:无法识别的选择器发送到实例0x6b80390'
2012-01-19 16:58:06.671 CBF [11738:fe03] - [__ NSCFDictionary _hasPrecomputedKeyOrder]:无法识别的选择器发送到实例0x6d55040
2012-01-25 21:45:31.174 CBF [16911:1310b] - [__ NSArrayM _addPersistentStore:identifier:]:无法识别的选择器发送到实例0x6d59370
2012-01-25 21:45:31.175 CBF [16911:1310b] * 终止应用程序 未捕获的异常'NSInvalidArgumentException',原因:' - [__ NSArrayM _addPersistentStore:identifier:]:无法识别的选择器发送到实例0x6d59370'
答案 0 :(得分:4)
为什么不删除延迟实例化,而是在应用启动时立即创建协调器?