我在iOS 7+应用程序中使用
Core Data
,不需要保存用户的数据,应用程序需要的所有数据都向服务请求,并且可以随时恢复。因此,如果我在下一次应用程序更新中更改我的数据模型,我可以毫无问题地删除所有以前的数据并再次请求所有数据。但我不知道如何简单地用新的数据模型替换以前的数据模型,而不执行迁移,因为看起来我不需要这样做......
提前致谢
如果您的目标是 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 中调用
loadStores
一次,并且当您想要删除和重建数据库时调用 deleteAndRebuild
:)
案例 1:您正在使用 SQLite 存储
如果您的商店类型是
NSSQLiteStoreType
,则这适用。即使您打算不时删除数据,坚持使用 SQLite 也不是一个坏主意,因为它使您可以灵活地将缓存数据保留在磁盘上,只要您愿意,并且仅在更改数据时才删除它。模型,并且您不想应用任何迁移。
快速解决方案?当您初始化核心数据时,请在启动时删除
NSPersistentStoreCoordinator
的存储。
例如,如果您使用的是 Apple 样板代码提供的默认 SQLite 存储:
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"cd.sqlite"]
您可以简单地删除该文件:
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];
然后像往常一样使用
storeURL
添加新的持久存储。NSPersistentStoreCoordinator
不会抱怨,但您的数据当然会丢失。
不言而喻,当您检测到数据模型发生更改时,您可以决定使用此解决方案,如果没有更改,则保留存储,以便您可以根据需要保留缓存的数据。
更新:
正如 TomHerrington 在评论中所建议的,为了确保您已完全删除旧存储,您还应该删除日志文件,如果您不处理它们,它们将来可能会回来困扰您.
如果您的商店文件名为
cd.sqlite
(如示例所示),则要删除的其他文件为 cd.sqlite-shm
和 cd.sqlite-wal
。
Core Data 的 WAL 日志记录模式已作为 iOS 7 和 OSX Mavericks 中的默认模式引入,正如 Apple 在 QA1809 中所报告的那样。
案例2:使用内存存储
按照建议,您可以使用
NSInMemoryStoreType
而不是 NSSQLiteStoreType
切换到内存存储。在这种情况下,擦除存储要容易得多:所有数据都驻留在内存中,当您的应用程序停止运行时,所有数据都会消失,磁盘上不会留下任何内容供您清理。下次,您可能会加载完全不同的模型,而无需任何迁移,因为没有数据要迁移。注:
这两种方法都是可行的,各有利弊,而且我相信还可能有其他策略。最后,您应该掌握所有要素来决定针对您的具体情况的最佳方法。
我认为
destroyPersistentStoreAtURL
NSPersistentStoreCoordinator
的方法就是你想要的。
它将删除数据存储和日志文件以及所有其他需要删除的内容。
查看 Apple 文档。
好的,所以我需要在我的应用程序中执行此操作,最终编写了以下函数。
注意:在加载 CoreData 存储之前调用此函数(我将其添加到应用程序(它是一个 swiftUI 应用程序)的 init() 中,这似乎有效。
另请注意,上述答案指的是
destroyPersistentStore(at: url, ofType: storeType, options: nil)
对我不起作用,因为它似乎没有删除 .sqlite-wal 文件或 sqlite.shm 文件。
class CoreDataContext {
static let datamodelName = "cedarca"
static let storeType = "sqlite"
static let persistentContainer = NSPersistentContainer(name: datamodelName)
class func deleteAndRebuild() {
let url = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0].appendingPathComponent("\(datamodelName).\(storeType)")
let url1 = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0].appendingPathComponent("\(datamodelName).sqlite-shm")
let url2 = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0].appendingPathComponent("\(datamodelName).sqlite-wal")
if FileManager.default.fileExists(atPath: url.path) {
do {
try FileManager.default.removeItem(at: url)
try FileManager.default.removeItem(at: url1)
try FileManager.default.removeItem(at: url2)
} catch {
print(error)
}
}
}
}