【发布时间】:2014-08-01 06:02:47
【问题描述】:
如WWDC 2014 session 225(Core Data 中的新增功能)中所述,iOS 8 和 OS X Yosemite 上的 Core Data 现在支持命令行参数 -com.apple.CoreData.ConcurrencyDebug 1 以启用检测违反 Core Data 并发合同的断言。
在我的实验中,我发现它在 iOS 8 beta 1 下工作(在设备和模拟器上),但我似乎发现了一个误报,即框架抛出了多线程违规异常它不应该这样做的地方。至少我是这么认为的。
问题:下面的代码是正确的还是我做的事情违反了 Core Data 的线程模型?
我所做的是设置一个非常简单的 Core Data 堆栈(为简单起见,使用内存存储)和一个名为 backgroundContext 的托管对象上下文,并具有私有队列并发性。然后我在该上下文中调用performBlockAndWait { },并在该块中创建一个新的托管对象,将其插入上下文中并保存。
保存操作是我从 Core Data 获取多线程冲突异常的地方。
var backgroundContext: NSManagedObjectContext?
func setupCoreDataStackAndViolateThreadingContract()
{
let objectModelURL = NSBundle.mainBundle().URLForResource("CoreDataDebugging", withExtension: "momd")
let objectModel: NSManagedObjectModel? = NSManagedObjectModel(contentsOfURL: objectModelURL)
assert(objectModel)
// Set up a simple in-memory Store (without error handling)
let storeCoordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: objectModel)
assert(storeCoordinator)
let store: NSPersistentStore? = storeCoordinator!.addPersistentStoreWithType(NSInMemoryStoreType, configuration: nil, URL: nil, options: nil, error: nil)
assert(store)
// Set up a managed object context with private queue concurrency
backgroundContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
assert(backgroundContext)
backgroundContext!.persistentStoreCoordinator = storeCoordinator!
// Work on the background context by using performBlock:
// This should work but throws a multithreading violation exception on
// self.backgroundContext!.save(&potentialSaveError)
backgroundContext!.performBlockAndWait {
NSEntityDescription.insertNewObjectForEntityForName("Person", inManagedObjectContext: self.backgroundContext!) as NSManagedObject
person.setValue("John Appleseed", forKey: "name")
var potentialSaveError: NSError?
// In the following line: EXC_BAD_INSTRUCTION in
// `+[NSManagedObjectContext __Multithreading_Violation_AllThatIsLeftToUsIsHonor__]:
let didSave = self.backgroundContext!.save(&potentialSaveError)
if (didSave) {
println("Saving successful")
} else {
let saveError = potentialSaveError!
println("Saving failed with error: \(saveError)")
}
}
}
我在 Objective-C 中测试了基本相同的代码并得到了相同的结果,所以我怀疑这是一个 Swift 问题。
编辑:如果你想自己运行代码,I have put a project on GitHub(需要 Xcode 6/iOS 8 beta)。
【问题讨论】:
-
iOS 8 beta 的东西 = NDA 涵盖...?
-
哦,酷!没关系! :)
标签: ios multithreading core-data ios8