我试图在第一次运行时使用 sqlite
文件将数据预加载到核心数据。我首先创建了一个xcdatamodeld
文件,然后使用python生成了sqlite
数据库,它的数据结构与我所说的xcdatamodeld
完全相同。
@main
struct ArgosApp: App {
static var isFirstLaunch = isAppAlreadyLaunchedOnce()
// MARK:- Initialise Core Data Stack
var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "Argos")
// if it is, load data from sql
if ArgosApp.isFirstLaunch {
guard let seededDataURL = Bundle.main.url(forResource: "karate", withExtension: "sqlite") else {
fatalError("Fail to find")
}
let storeUrl = ArgosApp.getDocumentsDirectory().appendingPathComponent("karate.sqlite")
if !FileManager.default.fileExists(atPath: (storeUrl.path)) {
try! FileManager.default.copyItem(at: seededDataURL, to: storeUrl)
}
let description = NSPersistentStoreDescription()
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
description.url = storeUrl
description.type = "sqlite"
container.persistentStoreDescriptions = [description]
// ERROR came in here: Thread 1: "Unsupported store type."
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}
// else, load from core data
else {
container.loadPersistentStores { storeDescription, error in
if let error = error as NSError? {
// TODO:- More decent error handling
fatalError("Unresolved error \(error), \(error.userInfo)")
}
}
}
return container
}()
var body: some Scene {
WindowGroup {
let context = persistentContainer.viewContext
let categories = Category.fetchAllCategories(context: context) ?? []
// Pass the persistent container to the view as environment object
ChallengeChooser(categories: categories)
.environment(\.managedObjectContext
,context)
}
}
// Detect if it's the first-launch
static func isAppAlreadyLaunchedOnce() -> Bool {
let defaults = UserDefaults.standard
if let _ = defaults.string(forKey: "isAppAlreadyLaunchedOnce") {
print("App already launched")
return false
} else {
defaults.set(true, forKey: "isAppAlreadyLaunchedOnce")
print("App launched first time")
return true
}
}
func saveContext (context: NSManagedObjectContext) {
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
static func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
}
当我尝试加载数据库时出现错误
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unsupported store type.'
这是我用 sqlite3 运行的代码,我在上面添加了一些测试数据,所以 difficulty
和 explanation
列都是 NULL。
cur.execute("""
CREATE TABLE category (
name VARCHAR(40) PRIMARY KEY
);
""")
cur.execute("""
CREATE TABLE video (
url VARCHAR(100) PRIMARY KEY,
explanation VARCHAR(300),
difficulty INT,
category VARCHAR(40),
FOREIGN KEY(category) REFERENCES category(name)
ON DELETE CASCADE
ON UPDATE CASCADE
);
""")
这就是我的 xcdatamodeld
的样子,我将 name
和 url
设置为非可选。