我有将一些对象插入Core Data存储中的方法
func insert(_ e: Entity, completion: @escaping (Result<Entity, Error>) -> Void) {
storage.persistentContainer.performBackgroundTask { [weak self] context in
guard let self = self else { return }
}
}
我也有这样的测试用例,只有上一次changeExpectation失败,因为没有收到此通知。
func test_whenMovieSaved_shouldBeRetrivable() {
// given
let dao = MoviesDao(storage: storage)
let movie = Movie(id: 1, title: "Test Title", posterPath: nil, overview: "Test Details", releaseDate: nil)
let insertExpectation = self.expectation(description: "Should insert entity.")
let loadExpectation = self.expectation(description: "Should load entity.")
let changeExpectation = self.expectation(forNotification: .NSManagedObjectContextDidSave, object: storage.persistentContainer.viewContext, handler: nil)
// when
dao.insert(movie) { (result) in
guard let e = try? result.get() else {
XCTFail("Should get valid entity back.")
return
}
XCTAssertEqual(movie, e)
insertExpectation.fulfill()
dao.load(id: "\(movie.id)") { result in
guard let e = try? result.get() else {
XCTFail("Should load valid entity back.")
return
}
XCTAssertEqual(movie, e)
loadExpectation.fulfill()
}
}
// then
wait(for: [insertExpectation, loadExpectation], timeout: 0.2)
wait(for: [changeExpectation], timeout: 2)
}
我什至尝试添加这样的内容,但是并没有强制发送通知 self.storage.saveContext(context)
NSManagedObjectContext.mergeChanges(fromRemoteContextSave: [NSInsertedObjectsKey: insertedObjectIds], into: [self.storage.persistentContainer.viewContext])
completion(.success(e))
在创建persistentCoordinator时,我也有类似的东西
container.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
container.viewContext.undoManager = nil
container.viewContext.shouldDeleteInaccessibleFaults = true
container.viewContext.automaticallyMergesChangesFromParent = true
答案 0 :(得分:0)
我想我终于找到了解决这个问题的方法。当我使用performBackgroundTask {
中的上下文时,它在stack.saveContext(context)方法中它不仅需要调用背景context.save(),还需要调用viewContext.save()。
在我的CoreDataStack中,现在有这样的方法
func saveContextAsync(_ context: NSManagedObjectContext) {
guard context != mainContext else {
saveContext()
return
}
context.perform {
do {
try context.save()
} catch let error as NSError {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
self.saveContextAsync(self.mainContext)
}
}
func saveContext(_ context: NSManagedObjectContext) {
guard context != mainContext else {
saveContext()
return
}
context.performAndWait {
do {
try context.save()
} catch let error as NSError {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
self.saveContext(self.mainContext)
}
}
func saveContextAsync() {
let context = mainContext
// Save all the changes just made and reset the context to free the cache.
context.perform {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
// Reset the context to clean up the cache and low the memory footprint.
context.reset()
}
}
func saveContext() {
let context = mainContext
// Save all the changes just made and reset the context to free the cache.
context.performAndWait {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
// Reset the context to clean up the cache and low the memory footprint.
context.reset()
}
}