CoreData - 使用执行和后台线程获取 NSManagedObject

CoreData - Fetch NSManagedObject with perform and background thread

我正在开发一个 SDK,它仅使用 1 个 NSManagedObjectContext,类型为 privateQueueConcurrencyType

为了获取对象,我使用 perform() 然后将结果传递给闭包。

我从后台线程调用此方法,并在后台线程(可能与调用它的线程不同)上使用结果。

我知道在线程之间传递对象是不行的,但我对我今天处理它的方式不满意。 我处理它的方式是,每个 NSManagedObject 都映射到 "normal" Swift 对象,然后我使用 swift 对象。

例如: Foreach NSManagedObject 从结果中,我创建了新对象(不是 NSManagedObject)然后我使用这些对象。

我想使用 NSManagedObjects 而不是创建包含相似数据的新数据。

最好的方法是什么? 我还能使用 NSManagedObject 吗?

func getRecordsByPredicate<T: NSManagedObject>(type: T.Type, predicate: NSPredicate, success: @escaping (_ record: [T]?) -> Void, failure: @escaping () -> Void) {

    self.context.perform {
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: String(describing: type.self))
        fetchRequest.includesPropertyValues = false
        fetchRequest.predicate = predicate

        do {
            let results = try context.fetch(fetchRequest)
            success(results as? [T])
        } catch {
           print(error.localizedDescription)
           failure()

        }
    }
}

最多很难提供涉及 CoreData 的 API。

您不能只公开 API 中的托管对象,因为它们与您的库私有的特定线程或调度队列相关联。您还需要客户端传递托管对象上下文,它定义了客户端将在其中使用托管对象的执行上下文。

如果你的内部 MOC 和客户端的 MOC 不一样,API 不可避免地变成异步的——否则它会阻塞一个线程。

您可能需要此 API 只能在主线程上使用,并且您的库也注意使用相同的 MOC。这当然有一些缺点,可能使 API 异步只是其中之一。

由于您也不能强迫开发人员阅读您的文档,因此第一个使用您的 API 的开发人员可能不会从主线程调用它。 ;)

另一种选择是让客户端将闭包传递给 API,然后在正确的执行上下文中从您的库中调用它。这也使得 API 异步,并且还需要开发人员对 CoreData 有深入的了解,因为她获得了 CoreData 托管对象。

您使用 "Swift" 值的第一种方法可能是处理此问题的最佳方法。使 CoreData 成为您的库的 "implementation detail",并为开发人员省去使用 CoreData 时的麻烦。