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

Posted

技术标签:

【中文标题】Swift CoreData:错误:严重的应用程序错误。在核心数据更改处理期间捕获到异常。【英文标题】:Swift CoreData: error: Serious application error. Exception was caught during Core Data change processing. 【发布时间】:2015-11-06 08:52:19 【问题描述】:

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

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

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

【问题讨论】:

绝大多数 iOS 和 OS X 应用程序和库都是用 ObjectiveC 编写的。你至少应该学会阅读ObjectiveC,不管你能不能用它编写功能代码。 @JodyHagins 那条评论根本没有帮助。 也许...我只是想找到一个简单的解决方案... 【参考方案1】:

您需要创建一个私有队列并发类型的私有 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 Concurrency Guide 以获得良好的理解。

【讨论】:

访问数据库通常是通过异步连接到服务器(发布请求,像这样:let task = session.dataTaskWithRequest(requestToServer, completionHandler: data, response, error -> Void in //连接到数据库 ) 还不够吗? @MosTelecom 否,这意味着您与 db 的连接将在单独的线程上异步运行,但您需要确保它不使用主托管对象上下文。这将有助于防止同时通过同一个 moc 访问数据库。 @Alex 我也面临同样的问题。你解决了这个问题吗?请告诉我。我尝试了很多方法,但我无法解决这个问题。 @Mohanaraj.C 看,我可以向您推荐的一件事是将您的项目升级到 Swift 4.1 并将应用程序的最低版本升级到 iOS 10.0,因为 CoreData 中的这个版本可用 NSPersistentContainer。它将取代您当前的 CoreDataStack,并允许您避免崩溃。 @Alex 目前我正在使用 swift 4.1 和最低版本的应用程序 10.0,但我仍然只在一段时间内面临崩溃问题。错误:严重的应用程序错误。在核心数据更改处理期间捕获到异常。这通常是 NSManagedObjectContextObjectsDidChangeNotification 观察者中的一个错误。 *** 集合 <__nscfset:> 在枚举时发生了突变。与 userInfo (null)【参考方案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)")
    
)

【讨论】:

【参考方案3】:

只是在里面调用你的 CoreData 函数

DispatchQueue.main.async 

...


为我工作

【讨论】:

【参考方案4】:

您可以为此创建一个扩展并将save() 函数包装成这样的东西,因此您只需要使用此函数而不是save()

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

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

【讨论】:

以上是关于Swift CoreData:错误:严重的应用程序错误。在核心数据更改处理期间捕获到异常。的主要内容,如果未能解决你的问题,请参考以下文章

CoreData:错误:严重的应用程序错误。在核心数据更改处理期间捕获到异常

CoreData:错误:严重的应用程序错误。在核心数据更改处理期间捕获到异常

如何解决由于 iCloud 合并而导致的“CoreData:错误:严重的应用程序错误”?

CoreData 严重应用程序错误:实体不符合键值编码

Swift 3.0 Coredata - Appdelegate & managedObjectContext 抛出 EXC_BAD_ACCESS 错误

Swift 4,CoreData:错误:无法加载名为 textTabelView 的模型