【发布时间】:2022-01-18 14:56:59
【问题描述】:
我正在尝试将应用程序从 Swift 迁移到 SwiftUI,但在处理 Core Data 时遇到了困难。我在同一个包标识符下运行 Swift 和 SwiftUI 应用程序,因此它们访问相同的底层数据,但是虽然我对两者使用相同的 xcdatamodeld 模型名称,但它们都指向不同的数据库。
我需要做的是在 Swift 上运行应用程序并将数据加载到 Core Data 中。然后重新运行 SwiftUI 版本的应用,就可以加载相同的数据了。
这里是 Swift 版本的代码:
class DataStore {
static let sharedDataStore = DataStore()
var managedContext: NSManagedObjectContext!
lazy var coreDataStack = CoreDataStack()
fileprivate init() {
self.managedContext = coreDataStack.context
}
func createParcours() -> Parcours {
let parcours = Parcours(context: managedContext)
parcours.timeStamp = NSDate()
return parcours
}
func deleteParcours(_ toDelete: Parcours) {
managedContext.delete(toDelete)
self.saveParcours()
}
func saveContext(parcours: Parcours?) {
if let parcours = parcours {
encodeParcours(parcours)
}
coreDataStack.saveContext()
}
}
class CoreDataStack {
let modelName = "MyParcours" // Exactly same name as name.xcdatamodeld
fileprivate lazy var applicationDocumentsDirectory: URL = {
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return urls[urls.count-1]
}()
lazy var context: NSManagedObjectContext = {
var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = self.psc
return managedObjectContext
}()
fileprivate lazy var psc: NSPersistentStoreCoordinator = {
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.appendingPathComponent(self.modelName)
do {
let options = [NSMigratePersistentStoresAutomaticallyOption: true]
try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: options)
} catch {
// Report any error we got.
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as AnyObject?
dict[NSLocalizedFailureReasonErrorKey] = "There was an error creating or loading the application's saved data." as AnyObject?
dict[NSUnderlyingErrorKey] = error as NSError
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
// Replace this with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
abort()
}
return coordinator
}()
fileprivate lazy var managedObjectModel: NSManagedObjectModel = {
let modelURL = Bundle.main.url(forResource: self.modelName, withExtension: "momd")!
return NSManagedObjectModel(contentsOf: modelURL)!
}()
func saveContext () {
guard context.hasChanges else {return}
do {
try context.save()
} catch let error as NSError {
print("Unresolved error: \(error), \(error.userInfo)")
}
}
}
在 SwiftUI 版本中,我生成 NSPersistentContainer() 并将其注入 ContentView:
class DataController: ObservableObject {
let container = NSPersistentContainer(name: "MyParcours")
init() {
container.loadPersistentStores { NSEntityDescription, error in
if let error = error {
print("Core Data failed to load: \(error.localizedDescription)")
}
}
}
}
@main
struct MySwiftUIApp: App {
@StateObject private var dataController = DataController()
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, dataController.container.viewContext)
}
}
}
我哪里出错了?
【问题讨论】:
标签: swift core-data swiftui core-data-migration