我有一个连接到互联网并将数据存储在SQL数据库中的应用程序。我用iOS4测试过,它完全可以正常工作。当我升级到新版本时,我得到一个NSInternalInconsistencyException,原因如下:
'_ obtainOpenChannel - NSSQLCore 0x951a640:没有可用的数据库通道'
从我可以收集到的内容来看,我的数据库在不应该被访问时被访问,尽管我无法理解其中的位置或原因。
有人可以帮我找到并正确诊断我的问题吗?
答案 0 :(得分:5)
我发现了这个东西:
当我在与创建托管上下文的线程不同的线程中访问托管对象的关系时,我得到了错误(在其他一些看似随机出现的错误中)。已经有一些更改了iOS5中对托管对象的并发访问(请参阅此处http://developer.apple.com/library/ios/#releasenotes/DataManagement/RN-CoreData/_index.html#//apple_ref/doc/uid/TP40010637) - 尽管文档声明默认行为应该像iOS5之前一样,但显然不是这样,我的代码在iOS4中没有问题。 2。
目前,我的解决方法是在主线程中执行所有关系访问功能,将数据存储在数组中,并通过该数组访问其他线程中所需的数据。至少没有错误。这不是我认为的“好”解决方案,因为我应该(并且会)改变我同时访问托管对象的方式,但我现在不会匆忙改变它。
答案 1 :(得分:1)
NSManagedObjectContext
的默认并发类型为NSConfinementConcurrencyType
,这意味着它只能由单个线程使用。来自文档:
您承诺除了以外的任何线程都不会使用上下文 你创建它的那个。
您可以创建一个由专用队列支持的托管对象上下文,以实现多线程使用:
[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]
要使用来自其他线程的托管对象上下文,请使用performBlock:
(asyncronous)或performBlockAndWait:
(同步),例如
__block NSArray *results;
[[self managedObjectContext] performBlockAndWait:^{
results = [[self managedObjectContext] executeFetchRequest:request error:&error];
}];
// do something with results
文档说您不需要使用创建托管对象上下文的线程中的块API。
另一个选择是为每个线程创建单独的托管对象上下文。
有关详细信息,请参阅iOS 5 release notes。