Core Data:如何删除和重建数据存储?

Posted

技术标签:

【中文标题】Core Data:如何删除和重建数据存储?【英文标题】:Core Data: how to just delete and rebuild the data store? 【发布时间】:2015-03-13 07:54:54 【问题描述】:

我在不需要保存用户数据的 ios 7+ 应用程序中使用Core Data,应用程序需要的所有数据都请求服务,并且可以随时恢复。因此,如果我在下一次应用程序更新中更改我的数据模型,我可以删除所有以前的数据并再次请求它们。但我不知道如何简单地用新的数据模型替换以前的数据模型,而不执行迁移,因为看起来我不需要这样做......

提前致谢

【问题讨论】:

你试过内存存储吗? @sim 有人告诉我使用SQLite 存储,但是...我在哪里可以找到有关内存选项的文档? 在 addPersistentStoreWithType 而不是 NSSQLiteStoreType 中,只需使用 NSInMemoryStoreType 并照常使用 Core Data 【参考方案1】:

案例 1:您使用的是 SQLite 商店

这适用于您的商店类型为 NSSQLiteStoreType。即使您打算不时删除数据,坚持使用 SQLite 也不是一个坏主意,因为它使您可以灵活地将缓存数据保留在磁盘上,只要您愿意,并且只有在您更改数据时才将其删除模型并且您不想应用任何迁移。

快速解决方案?在初始化 Core Data 时,在启动时删除 NSPersistentStoreCoordinator 的存储。 例如,如果您使用 Apple 的样板代码提供的默认 SQLite 存储:

NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"cd.sqlite"]

您可以简单地删除文件:

[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];

然后像往常一样使用storeURL 添加新的持久存储。 如果您有新模型并且不需要任何迁移,您的NSPersistentStoreCoordinator 不会抱怨,但您的数据当然会丢失。

不用说,当您检测到数据模型发生更改时,您可以决定使用此解决方案,如果没有更改,则不考虑存储,这样您就可以根据需要保留缓存数据。

更新:

根据 cmets 中 TomHerrington 的建议,为确保您已完全删除旧存储,您还应该删除日志文件,如果您将来可能会回来困扰您不要照顾他们。 如果您的商店文件名为cd.sqlite,如示例中所示,则要删除的附加文件为cd.sqlite-shmcd.sqlite-wal

正如 Apple 在QA1809 中所报告的那样,Core Data 的 WAL 日志模式是 iOS 7 和 OSX Mavericks 中的默认设置。

案例 2:使用内存存储

按照建议,您可以切换到内存存储,使用 NSInMemoryStoreType 而不是 NSSQLiteStoreType。在这种情况下擦除存储要容易得多:您的所有数据都驻留在内存中,当您的应用程序停止运行时,所有数据都会消失,磁盘上不会留下任何内容供您清理。下次,您可能会加载一个完全不同的模型,而无需进行任何迁移,因为没有要迁移的数据。 但是,按原样实施的此解决方案不会让您在会话之间缓存数据,这看起来像是您希望在应用程序更新之间执行的操作(即,只有在更新应用程序和模型时才必须删除存储更改,而将其保存在磁盘上可能会很有用)。

注意:

这两种方法都是可行的,各有利弊,我相信也可能有其他策略。最后,您应该拥有所有要素来决定在您的特定情况下最佳方法是什么。

【讨论】:

我只是建议不要在您处于应用程序中间时删除持久存储文件,即在添加持久存储之后。 你说得对。我认为这是理所当然的,因为我们正在讨论在应用程序更新中更改数据模型,这将在启动时完成,在初始化 Core Data 时。但是感谢您的建议,我会添加一个注释:) 您还需要删除日志文件,因为持久存储中的一些(可能全部)数据实际上在这些文件中。 我的日志文件从来没有遇到过任何问题。 @TomHarrington 您在不删除它们后是否遇到任何不一致? 感谢@TomHarrington 的评论。我的日记文件还没有任何问题,但我明白你的意思。我的运气可能是由于我的经验有限。让我更新我的答案并提及您最好删除的其他文件(-wal 和 -shm)以完全确保您已删除旧数据。谢谢!【参考方案2】:

适用于 iOS 9 或更高版本的 Swift 解决方案

共享的 CoreData 管理器:

class CoreDataContext 
    static let datamodelName = "CoreDataTests"
    static let storeType = "sqlite"

    static let persistentContainer = NSPersistentContainer(name: datamodelName)
    private static let url: URL = 
        let url = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0].appendingPathComponent("\(datamodelName).\(storeType)")

        assert(FileManager.default.fileExists(atPath: url.path))

        return url
    ()

    static func loadStores() 
        persistentContainer.loadPersistentStores(completionHandler:  (nsPersistentStoreDescription, error) in
            guard let error = error else 
                return
            
            fatalError(error.localizedDescription)
        )
    

    static func deleteAndRebuild() 
        try! persistentContainer.persistentStoreCoordinator.destroyPersistentStore(at: url, ofType: storeType, options: nil)

        loadStores()
    

当您想删除和重建数据库时,只在 appDelegate 和 deleteAndRebuild 中调用一次 loadStores :)

【讨论】:

【参考方案3】:

我认为NSPersistentStoreCoordinatordestroyPersistentStoreAtURL 方法是你想要的。

它将删除数据存储和日志文件以及所有其他需要删除的内容。

看 Apple documentation。

【讨论】:

非常感谢您的回答。我相信这是正确的。但是 - 考虑到 CoreData 对象(上下文、实体、PSCoordinator、PSStore 等)的层次结构和依赖关系,随时调用“destroyPersistentStoreAtURL”是否安全?在破坏之前不应该做一些“关闭”仪式吗?您在这方面有何经验?

以上是关于Core Data:如何删除和重建数据存储?的主要内容,如果未能解决你的问题,请参考以下文章

从 Core Data 中删除和添加存储

用户更新软件后如何保存Core Data?

如何 VACUUM 一个 Core Data SQLite 数据库?

当应用程序从 4.0 中的任务列表中删除时,Core Data 存储消失

如何使用 Restkit 和 Core Data 存储对象和种子预加载数据

如何通过删除和重新安装 App 将数据持久化在 Core Data 中