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 时的麻烦。
我正在开发一个 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 时的麻烦。