我使用performBackgroundTask
函数从firebase中提取数据,将其与已存储在Core Data中的数据进行比较,将新数据保存到Core Data中,并在完成时调用完成处理程序。核心数据和并发
我明白,核心数据不是线程安全的,但我试图同时做到这一点。
static func cache(completion: @escaping (Void) -> Void) {
CoreDataHelper.persistentContainer.performBackgroundTask { (context) in
let dispatchGroup = DispatchGroup()
// fetch previously saved Core Data from main thread (1) and filter them (2)
let newsSourceIDs = NewsSourceService.getSaved().filter{$0.isEnabled}.map{$0.id!}
let oldArticleURLs = ArticleService.getSaved().map{$0.url!}
// create firebase database reference
let ref = Database.database().reference()
Constants.Settings.timeOptions.forEach { time in
let timeRef = ref.child("time\(time)minutes")
newsSourceIDs.forEach { newsSourceID in
dispatchGroup.enter()
// pull from Firebase Database
timeRef.child(newsSourceID).observeSingleEvent(of: .value, with: { (snapshot) in
guard let newsSourceDict = snapshot.value as? [String: [String:String]] else {
return
}
newsSourceDict.values.forEach { articleDict in
dispatchGroup.enter()
if oldArticleURLs.contains(articleDict["url"]!) {
dispatchGroup.leave()
return
}
// create article entity with firebase data
let article = Article(context: context)
article.date = articleDict["date"]
article.source = newsSourceID
article.time = Int16(time)
article.title = articleDict["title"]
article.url = articleDict["url"]
article.urlToImage = articleDict["urlToImage"]
dispatchGroup.leave()
}
dispatchGroup.leave()
})
}
}
// when done, save and call completion handler (3)
dispatchGroup.notify(queue: .main) {
do {
try context.save()
completion()
} catch {
fatalError("Failure to save context: \(error)")
}
}
}
}
从核心数据功能获取:
static func getSaved() -> [Article] {
let fetchRequest: NSFetchRequest<Article> = Article.fetchRequest()
do {
let results = try CoreDataHelper.managedContext.fetch(fetchRequest)
return results
} catch let error as NSError {
print("Could not fetch \(error)")
}
return []
}
- 我可以从主线程中
performBackgroundTask
获取核心数据? - 我应该与高级别
filter
功能或使用特殊的批量要求(我能做到这一点的同时?) - 我如何使用
dispatchGroup.notify(queue:)
确定何时核心数据的创建和保存完整过滤器?
context.save()同步发生(或足够快),完成处理程序将能够访问数据? – caziz
和哪个队列应该通知使用(不是.main?) – caziz
保存是同步的。要通知的队列取决于通知块中的代码需要执行的操作。如果它正在更新UI,那么主队列。 –