CoreData CRUD操作测试,无NSManagedObjectDidSave通知

时间:2019-09-22 12:16:54

标签: ios core-data

我有将一些对象插入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

1 个答案:

答案 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()
        }
    }