Основные данные Concurrency Отладка: ложные положительные

Как упоминалось в сессии WWDC 2014 225 (Что нового в основных данных), Основные данные на iOS 8 и OS X Yosemite теперь поддерживают аргумент командной строки -com.apple.CoreData.ConcurrencyDebug 1 для включения утверждений, которые обнаруживают нарушения контракта Core Data concurrency.

В моих экспериментах с этим я обнаружил, что он работает под iOS 8 beta 1 (как на устройстве, так и в симуляторе), но я, кажется, нашел ложный результат, т.е. фреймворк бросает исключение нарушения многопоточности где он не должен этого делать. По крайней мере, я верю.

Вопрос: верен ли код ниже или я делаю что-то, что нарушает модель потоковой обработки Core Data?

Я создаю очень простой стек Core Data (с сохранением в памяти для простоты) с контекстом управляемого объекта с именем backgroundContext с приватной очередью concurrency. Затем я вызываю 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.

Изменить: если вы хотите запустить код самостоятельно, Я поставил проект на GitHub (требуется Xcode 6/iOS 8 beta).

Ответ 1

Apple подтвердила это как ошибку. Он был исправлен с Xcode 6 beta 4.