更改应用程序状态时,CoreData 提取请求 returns 具有 nil 属性的对象

CoreData fetch request returns an object with nil properties when changing app state

我有一些代码可以帮助管理当前的托管对象上下文

var currentContext: NSManagedObjectContext {
    if Thread.isMainThread {
        return mainContext
    } else {
        return backgroundContext
    }
}

var mainContext: NSManagedObjectContext {
    return persistentContainer.viewContext
}

lazy var backgroundContext: NSManagedObjectContext = {
    let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
    context.parent = mainContext
    
    return context
}()

获取函数

public func entities(_ fetchOptions: FetchOptions) -> [T] {
    let fetchRequest = NSFetchRequest<T>(entityName: T.entityName)
    
    switch fetchOptions {
    case let .filtered(predicate):
        fetchRequest.predicate = predicate
    case let .sorted(sortDescriptors):
        fetchRequest.sortDescriptors = sortDescriptors
    case let .filteredAndSorted(predicate, sortDescriptors):
        fetchRequest.predicate = predicate
        fetchRequest.sortDescriptors = sortDescriptors
    case .all:
        fetchRequest.sortDescriptors = []
    }
    
    fetchRequest.returnsObjectsAsFaults = false
    
    let context = CoreDataContextProvider.provider.currentContext
    
    return (try? context.fetch(fetchRequest)) ?? []
}

假设我有一个从服务器获取一些数据并将其写入 CoreData 的请求。当我在前台使用该应用程序时,一切正常,但是当我进入后台时,例如,切换到另一个应用程序,然后返回,从当前上下文获取特定实体的请求 returns 类似

SomeEntity {
   var property1 = 0;
   var property2 = nil;
   var property3 = nil;
   ... etc
}

后台上下文中的数据是正确的,我在切换回主上下文后就得到了这个行为。

我已经尝试在 UIApplication.didEnterBackgroundNotificationUIApplication.willEnterForegroundNotification 上保存当前上下文,因此无论如何都会推送更改,但它似乎没有帮助。

此外,我尝试在 NSManagedObject.didSaveObjectsNotification 上合并主要和背景上下文,得到了相同的结果,但我不排除我在这里做错了。

当我只使用主上下文时,一切似乎都工作正常,但我变得严重 UI 偶尔会死机。

解决方案是让主上下文为我做这些合并工作,实际上有一种方法可以创建新的背景上下文,而不会很麻烦:

persistentContainer.newBackgroundContext()

现在一切正常