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

标签 ios objective-c swift core-data

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

你好,

我的应用程序实际上运行稳定,但在极少数情况下它会崩溃并显示此错误消息...

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'

...当它尝试保存当前上下文时(我代码中的这部分仍在 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]);
        }
    });
}

'很少'是指: 大多数客户从来没有遇到过这个问题,对于少数客户来说,它每天会发生几次。 尽管我尝试了几种方法来强制执行此错误(见下文),但在过去两天内我能够生成它 2 次。

这是设置:

  • 各自的数据在一个实体(表)中
  • NSFetchedResultsController 在 UITableView 中显示数据
  • 用户可以点击一个按钮来添加一条新记录。
  • 新记录只有一些基本数据,并向两个网络服务器发起两次 API 调用
  • 每个网络服务器响应都会更新记录
  • 两者都完成后(或由于超时而被取消),我只从上面调用了一次 saveChanges 函数。
  • 所有函数都使用由 NSPersistentContainer 创建的相同上下文,如下所示(这部分已经在 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
 }()

如果我能以某种方式重现错误,我就能找到合适的解决方案,但由于它几乎从未发生过,所以我被困住了。

您知道我如何重现上面的错误吗?或者您是否知道在我的案例中可能导致错误的原因是什么?

我已经尝试重现错误:

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

最佳答案

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

所有这些的细节在 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.

NSPersistentContainer 的一般方法是在主队列上专门使用 viewContext 之类的东西,并使用 performBackgroundTask 来处理后台操作,或者您可以使用 newBackgroundContext 生成背景上下文,并在其上使用 performperformAndWait 来操作从该上下文中获取的对象。

在上下文之间移动对象是通过在另一个上下文中获取相同的 objectID 来完成的(请记住,这将从存储中返回一个新实例)。

You can track down mistakes by adding -com.apple.CoreData.ConcurrencyDebug 1 to your scheme.当您这样做时,错误将立即陷入令人愉快的命名 __Multithreading_Violation_AllThatIsLeftToUsIsHonor__

关于iOS 核心数据 - 严重的应用程序错误 - 尝试插入 nil - 不到 1%,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55517083/

相关文章:

ios - 如何使我的类(class)符合外部协议(protocol)?它找不到它,但我的印象是我不应该在 .h 文件中导入

ios - 尝试发送带纬度和经度的 POST 参数

iphone - 在某个时间创建表示 "today"的 NSDate 对象

ios - 未在条件语句中执行 Segue

Swift - Cocoa - 更改窗口颜色?

iOS 蓝牙服务

ios - 分段控制 : titleForSegmentAtIndex returns null every time

c++ - 3d 游戏中的实时聊天框

ios - Xcode 7 Beta 5 - Storyboard 中缺少所有 subview

ios - UITableView 标题中的标题未显示?