Swift CoreData:错误:严重的应用程序错误。在Core Data更改处理期间捕获到异常。

时间:2015-11-06 08:52:20

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

我正在iOS上编写一个程序,我正面临着这个错误:

  

2015-11-06 10:57:24.289 NETFNET [2503:976392] CoreData:错误:严重的应用程序错误。在Core Data更改处理期间捕获到异常。这通常是NSManagedObjectContextObjectsDidChangeNotification的观察者中的错误。 - [__ NSCFSet addObject:]:尝试使用userInfo插入nil(null)   2015-11-06 10:57:24.293 NETFNET [2503:976392] ***由于未捕获的异常'NSInvalidArgumentException'终止应用程序,原因:' - [__ NSCFSet addObject:]:尝试插入nil'

我想从主线程和后台线程同时访问Data Base。我已经看到了很多针对Objective C的解决方案,但没有针对Swift的解决方案(我不知道Objective C ......)。不幸的是,我不知道如何使用Grand Central Dispatch,事实上,我的程序并不需要几个步骤(我的意思是它需要它,但如果某个线程丢失一个函数的信息一次,没有什么不好的意思发生)。我只想在Swift 1或2上拥有稳定的程序,所以我会感谢任何帮助。

4 个答案:

答案 0 :(得分:5)

您需要使用专用队列并发类型创建私有NSManagedObjectContext,并在后台线程上运行时使用它来访问CoreData。

假设我需要在后台运行数据库操作,我可以将该工作发送到后台线程

dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), {
        //call your background operation.
    })

然后在后台操作中,我可以创建一个私有NSManagedObjectContext为

let moc = … //Our primary context on the main queue

let privateMOC = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
privateMOC.parentContext = moc

privateMOC.performBlock {
    //operations
    do {
        try privateMOC.save()
    } catch {
        fatalError("Failure to save context: \(error)")
    }
}

阅读Apple的CoreData并发指南,以便在多线程上实现核心数据操作之前获得良好的理解。

答案 1 :(得分:2)

非常好。我试过了,它对我来说很好。 非常感谢你。

上一个代码:

        do {
            try CDHelper.shared.context.save()
        }
        catch let error as NSError {
            // Error mesajlarını ekle!!
            print("Could not fetch \(error), \(error.localizedDescription)")
            print("Could not fetch \(error), \(error.localizedFailureReason)")
        }


// MARK: - CONTEXT
lazy var context: NSManagedObjectContext = {
    let moc = NSManagedObjectContext(concurrencyType:.MainQueueConcurrencyType)
    moc.persistentStoreCoordinator = self.coordinator
    return moc
}()

// MARK: - MODEL
lazy var model: NSManagedObjectModel = {
    return NSManagedObjectModel(contentsOfURL:self.modelURL)!
}()

// MARK: - COORDINATOR
lazy var coordinator: NSPersistentStoreCoordinator = {
    return NSPersistentStoreCoordinator(managedObjectModel:self.model)
}()

lazy var modelURL: NSURL = {
    let bundle = NSBundle.mainBundle()
    if let url = bundle.URLForResource("Model", withExtension: "momd") {
        return url
    }
    print("CRITICAL - Managed Object Model file not found")
    abort()
}()

你应该这样改变代码:

let moc = NSManagedObjectContext(concurrencyType:.MainQueueConcurrencyType)
let privateMOC = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
privateMOC.parentContext = moc

privateMOC.performBlock({
    do {
        try privateMOC.save()
    } catch {
        fatalError("Failure to save context: \(error)")
    }
})

答案 2 :(得分:1)

在里面调用你的 CoreData 函数

DispatchQueue.main.async {

...

}

为我工作

答案 3 :(得分:0)

您可以为此创建一个扩展并将save()函数包装为类似的内容,因此您只需要使用此函数而不是save()

extension NSManagedObjectContext {
    func update() throws {
        let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
        context.parent = self

        context.perform({
            do {
                try context.save()
            } catch {
                print(error)
            }
        })
    }
}