iOS核心数据-严重的应用程序错误-尝试插入nil-小于1% [英] iOS Core Data - Serious application error - attempt to insert nil - in less than 1%

查看:75
本文介绍了iOS核心数据-严重的应用程序错误-尝试插入nil-小于1%的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

iOS核心数据-严重的应用程序错误-尝试插入nil

你好

我的应用程序实际上运行稳定,但是在极少数情况下,它会因该错误消息而崩溃...

2019-04-02 20:48:52.437172 + 0200 myAppName [4422:1595677] [错误]错误:严重的应用程序错误.在核心数据更改处理期间捕获到异常.这通常是NSManagedObjectContextObjectsDidChangeNotification的观察者中的错误.-[__ NSCFSet addObject:]:尝试使用userInfo插入nil(空)CoreData:错误:严重的应用程序错误.在核心数据更改处理期间捕获到异常.这通常是NSManagedObjectContextObjectsDidChangeNotification的观察者中的错误.-[__ NSCFSet addObject:]:尝试使用userInfo插入nil(空)2019-04-02 20:48:52.438246 + 0200 myAppName [4422:1595677] ***由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'-[__ NSCFSet addObject:]:尝试插入nil'

...当尝试保存当前上下文时(我代码中的这一部分仍在objc中):

 -(void)saveChanges{dispatch_async(dispatch_get_main_queue(),^ {NSError * err = nil;BOOL成功= [self-> context save:& err];如果(成功){NSLog(@保存上下文期间的错误消息:%@",[err localizedDescription]);}});} 

很少"是指:大多数客户从未遇到过该问题,很少有客户每天发生几次.在过去的两天内,尽管尝试了几种方法来强制执行此错误(见下文),但我仍然能够生成2次.

这是设置:

  • 各个数据在一个实体(表)中
  • NSFetchedResultsController在UITableView中显示数据
  • 用户可以单击一个按钮来添加新记录.
  • 新记录仅包含一些基本数据,并向两个Web服务器发起两个API调用
  • 每个网络服务器响应均会更新记录
  • 两者都完成(或由于超时而取消)后,我仅从上方调用一次saveChanges函数.
  • 所有功能都使用NSPersistentContainer创建的相同上下文,如下所示(此部分已经很快完成)

  @objc lazy varpersistentContainer:NSPersistentContainer = {让容器= NSPersistentContainer(名称:"myAppName")let description = NSPersistentStoreDescription(url:SomeHelper.urlForFileInDocFolder("storev7.data"))container.persistentStoreDescriptions = [说明]container.loadPersistentStores(completionHandler:{如果让error = error as NSError?{fatalError(未解决的错误\(错误),\(error.userInfo)")}})返回容器}() 

如果我能以某种方式重现该错误,我可以找到一个合适的解决方案,但是由于几乎永远不会发生,所以我被困住了.

您是否知道如何从上方重现错误?还是您有什么线索可能导致我的错误?

我已经尝试重现该错误的内容:

  • 创建记录记录
  • 在几秒钟内创建记录记录
  • 在打开/关闭/打开/关闭/...的互联网连接期间创建记录记录.
  • 在后台和主线程混合期间创建记录混乱(为此我从saveChanges中删除了调度)
  • 在API上创建具有不同延迟的记录(在网络服务器上添加了随机睡眠功能)
  • 长时间执行后,该应用在真实设备上运行了24小时,并每2分钟创建了一条记录
  • 所有的人

解决方案

NSManagedObjects仅限于单个队列.它们对于读取或写入而言不是线程安全的.读取NSManagedObject可能会导致错误,这是写操作.这意味着从主队列上下文(如 viewContext )检索到的NSManagedObjects无法传递到其他队列.

所有这些细节都在您可以通过添加 -com来跟踪错误.apple.CoreData.ConcurrencyDebug 1 插入到您的方案中.执行此操作时,错误将立即捕获在名为 __ Multithreading_Violation_AllThatIsLeftToUsIsHonor __ 的令人愉快的名称中.

iOS Core Data - Serious application error - attempt to insert nil

Hello,

My app runs actualy stable, but in seldom cases it crashes with this error message...

2019-04-02 20:48:52.437172+0200 myAppName[4422:1595677] [error] error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. -[__NSCFSet addObject:]: attempt to insert nil with userInfo (null) CoreData: error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. -[__NSCFSet addObject:]: attempt to insert nil with userInfo (null) 2019-04-02 20:48:52.438246+0200 myAppName[4422:1595677] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFSet addObject:]: attempt to insert nil'

...when it tries to save the current context (this part in my code is still in objc):

- (void)saveChanges
{
    dispatch_async(dispatch_get_main_queue(), ^{
        NSError *err = nil;
        BOOL succesful = [self->context save:&err];
        if (!succesful)
        {
            NSLog(@"ERROR MESSAGE DURING SAVING CONTEXT: %@", [err localizedDescription]);
        }
    });
}

'seldom' means: Most Customers do never experience the issue, for few customers it happens several times per day. I was able to produce it 2 times during the last two days although I tried several ways to force this error (see below).

This is the setup:

  • The respective data is in one Entity (table)
  • A NSFetchedResultsController shows the data in an UITableView
  • User can hit a button to add a new record.
  • New record has only some basic data and initiates two API calls to two webservers
  • Each webserver response does update the record
  • After both are done (or were cancelled due to timeout), I call the saveChanges function from above only once.
  • All functions use the same context created by NSPersistentContainer as follow (this part is already in swift)

@objc lazy var persistentContainer: NSPersistentContainer = {

        let container = NSPersistentContainer(name: "myAppName")
        let description = NSPersistentStoreDescription(url: SomeHelper.urlForFileInDocFolder("storev7.data"))
        container.persistentStoreDescriptions = [description]

        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })

        return container
 }()

If I could reproduce the error somehow, I could find an appropriate solution, but as it almost never happens, I'm stuck.

Do you have an idea how I could reproduce the error from above? Or do you have a clue what could cause the error in my case?

What I tried already to reproduce the error:

  • Create hundereds of record
  • Create hundereds of record in a few seconds
  • Create hundereds of record during switching internet connection on / off / on / off /...
  • Create hundereds of record during mixed from background and main thread (I removed the dispatch from saveChanges for that)
  • Create hundereds of record with different delays on the API (added random sleep function on the webserver)
  • Long time execution, the app run for 24 hours on a real device and created record each 2 minutes
  • Mixes of all of them

解决方案

NSManagedObjects are restricted to a single queue. They are not thread-safe for reading or writing. Reading an NSManagedObject can cause a fault, which is a write operation. That means that NSManagedObjects retrieved from a main queue context (like viewContext) cannot be passed to other queues.

The details of all of this are discussed in the Core Data Programming Guide:

NSManagedObject instances are not intended to be passed between queues. Doing so can result in corruption of the data and termination of the application. When it is necessary to hand off a managed object reference from one queue to another, it must be done through NSManagedObjectID instances.

The general approach with NSPersistentContainer is to use something like viewContext exclusively on the main queue, and to use performBackgroundTask to handle background operations, or you can use newBackgroundContext to generate a background context, and use perform or performAndWait on it to manipulate objects that are fetched from that context.

Moving an object between contexts is done by fetching the same objectID in the other context (keeping in mind that this will return a fresh instance from the store).

You can track down mistakes by adding -com.apple.CoreData.ConcurrencyDebug 1 to your scheme. When you do this, errors will immediately trap on the delightfully named __Multithreading_Violation_AllThatIsLeftToUsIsHonor__.

这篇关于iOS核心数据-严重的应用程序错误-尝试插入nil-小于1%的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆