初始化时内存中的CoreData容器为空 [英] In memory CoreData container is empty when initialized

查看:101
本文介绍了初始化时内存中的CoreData容器为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

tl; dr:


  1. 克隆项目: https://github.com/Jasperav/CoreDataInMemoryFail

  2. 运行测试并看到失败。为什么我的内存容器中没有任何数据,如何确定将有数据?

长:

我有一个带填充数据的sqlite文件,并且CoreData中有一个内存数据库。一些代码:

I have a sqlite file with filled data and I have an in-memory database in CoreData. Some code:

// ...
func createInMemoryPerformanceTestDatabase() -> NSPersistentContainer {
    let url = createPathToSomeSQLiteFile()
    let container = NSPersistentContainer(name: dataModelName, managedObjectModel: objectModel)
    let description = NSPersistentStoreDescription(url: url)

    description.type = NSInMemoryStoreType

    container.persistentStoreDescriptions = [description]

    container.loadPersistentStores { description, error in
        XCTAssertNil(error)
    }

    return container
}
// ...

尽管sqlite文件内部有数据,但我没有在使用容器创建的上下文中看到它。

Although the sqlite file has data inside it, I don't see it back inside my contexts I create with container.

创建内存数据库时,CoreData指向包含数据的sqlite文件时,查询数据库时看不到任何结果。我想查看sqlite文件中的数据。数据应该只加载到内存中。这是出于测试目的。

When I create an in-memory database with CoreData pointing to a sqlite file with data, I don't see any results when querying the database. I want to see the data inside the sqlite file. The data should just load all in memory. This is for testing purposes.

推荐答案

您尝试过的问题是,在将storeDescription的类型设置为NSInMemoryStoreType之前,将它们加载到容器中。由于storeDescription的类型表示为NSInMemoryStoreType,因此该api不会从您提供的文件URL中读取和填充数据。为了使api从文件url读取数据,storeDescription的类型必须是使用初始化程序 init(url:URL)初始化的类型,即<您可以使用strong> SQLite 。

The problem with what you have tried was that you set the type of your storeDescription as NSInMemoryStoreType before loading them into the container. Since, the type of storeDescription is stated as NSInMemoryStoreType the api won't read and populate data from the file URL you have provided. In order for the api to read the data from the file url, the type of storeDescription must be the one defined by initialising with the initialiser init(url: URL) which is SQLite in your case.

但是,如果您想拥有一个NSInMemoryStoreType类型的persistentStore,并且从文件url中读取了数据,则可以迁移persistentStore使用函数 migratePersistentStore:toURL:options:withType:error:的NSInMemoryStoreType类型的persistentContainer。您可以尝试下面的代码段。

However if you want to have a persistentStore of type NSInMemoryStoreType with data read from the file url, you can migrate the persistentStores of your persistentContainer with NSInMemoryStoreType type using function migratePersistentStore:toURL:options:withType:error:. You can try out the code snippet below.

import CoreData
import XCTest
@testable import CoreDataInMemoryFail


class CoreDataInMemoryFailTests: XCTestCase {

    private func createContainer(modify: (NSPersistentContainer) -> ()) -> NSPersistentContainer {
        let bundle = Bundle(for: type(of: self))
        let path = bundle.path(forResource: "InMemoryDatabase", ofType: "sqlite")!
        let url = URL(fileURLWithPath: path)
        let persistentContainer = createPersistentContainer(dataModelName: "InMemoryDatabase")
        let storeDescription = NSPersistentStoreDescription(url: url)

        persistentContainer.persistentStoreDescriptions = [storeDescription]
        persistentContainer.loadPersistentStores { description, error in
            XCTAssertEqual(storeDescription.type, description.type)
            XCTAssertNil(error)
        }

        modify(persistentContainer)
        return persistentContainer
    }

    func testFail() {
        let persistentContainer = createContainer(modify: { _ in })
        let inMemoryContainer = createContainer { persistentContainer in
            let coordinator = persistentContainer.persistentStoreCoordinator
            coordinator.persistentStores.forEach { (persistentStore) in
                do {
                    try coordinator.migratePersistentStore(persistentStore, to: NSPersistentContainer.defaultDirectoryURL(), options: nil, withType: NSInMemoryStoreType)
                } catch {
                    print("Error while migrating persistentStore")
                }
            }
        }

        let persistentContainerCoordinator = persistentContainer.persistentStoreCoordinator
        persistentContainerCoordinator.persistentStores.forEach { (persistentStore) in
            XCTAssertEqual(persistentStore.type, "SQLite")
        }

        let inMemoryContainerCoordinator = inMemoryContainer.persistentStoreCoordinator
        inMemoryContainerCoordinator.persistentStores.forEach { (persistentStore) in
            XCTAssertEqual(persistentStore.type, NSInMemoryStoreType)
        }

        let fetchRequest: NSFetchRequest<Person> = Person.fetchRequest()
        let persistentContainerCount = (try! persistentContainer.viewContext.fetch(fetchRequest)).count
        let inMemoryContainerCount = (try! inMemoryContainer.viewContext.fetch(fetchRequest)).count

        XCTAssertEqual(8, persistentContainerCount)
        XCTAssertEqual(persistentContainerCount, inMemoryContainerCount)
    }

}

在上面的代码段中,我还添加了断言以验证您的 inMemoryContainer 中的persistentStore类型是否为 NSInMemoryStoreType ,并且 persistentContainer 中的 SQLite 。希望对您有所帮助。

In the above snippet, I have also added asserts to verify whether persistentStore type is NSInMemoryStoreType in your inMemoryContainer and SQLite in your persistentContainer. Hope it helps.

这篇关于初始化时内存中的CoreData容器为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆