如何让 SwiftUI 与 Core Data 一起工作(在启动项目后)?

Posted

技术标签:

【中文标题】如何让 SwiftUI 与 Core Data 一起工作(在启动项目后)?【英文标题】:How do I get SwiftUI to work with Core Data (after starting a project)? 【发布时间】:2021-05-01 14:35:02 【问题描述】:

我在尝试让 Xcode 与 Core Data 一起工作时收到此错误。任何帮助将不胜感激。

Context in environment is not connected to a persistent store coordinator: <NSManagedObjectContext: 0x6000008a8820>

在注释掉所有其他环境后,持久化环境只在顶层使用,我仍然有同样的错误。

这是应用程序*** Swift 文件:

导入 SwiftUI 导入核心数据

@main
struct Draw_DailyApp: App 
    
let persistenceController = PersistenceController.shared
@Environment(\.scenePhase) var scenePhase

@FetchRequest(entity: Drawing.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Drawing.img, ascending: true)])



var orders: FetchedResults<Drawing>

@State var showOrderSheet = false


// Creating a global environment and placing it into the environment
@ObservedObject var searchObjectController: SearchObjectController = SearchObjectController()


var body: some Scene 
    WindowGroup 
        ContentView()
            .environment(\.managedObjectContext, persistenceController.container.viewContext)
            .environmentObject(self.searchObjectController)
    
    .onChange(of: scenePhase)  _ in
        persistenceController.save()
    

这里是使用持久化控制器的文件(Core Data xcdatamodeld 有一个名为 img 的二进制数据属性)

Persistence.Swift

    import CoreData
import UIKit

struct PersistenceController 
    static let shared = PersistenceController()
    
    func save() 
        let context = container.viewContext

        if context.hasChanges 
            do 
                try context.save()
             catch 
                // Show some error here
            
        
    

    static var preview: PersistenceController = 
        let result = PersistenceController(inMemory: true)
        let viewContext = result.container.viewContext
        for _ in 0..<10 
            let newItem = Drawing(context: viewContext)
            newItem.img = Data()
            newItem.date = "02081999"
        
        do 
            try viewContext.save()
         catch 
            // Replace this implementation with code to handle the error appropriately.
            // fatalError() 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.
            let nsError = error as NSError
            fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
        
        return result
    ()

    let container: NSPersistentContainer

    init(inMemory: Bool = false) 
        container = NSPersistentContainer(name: "DrawDaily")
        if inMemory 
            container.persistentStoreDescriptions.first?.url = URL(fileURLWithPath: "/dev/null")
        
        container.loadPersistentStores(completionHandler:  (storeDescription, error) in
            if let error = error as NSError? 
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() 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.
                /*
                Typical reasons for an error here include:
                * The parent directory does not exist, cannot be created, or disallows writing.
                * The persistent store is not accessible, due to permissions or data protection when the device is locked.
                * The device is out of space.
                * The store could not be migrated to the current model version.
                Check the error message to determine what the actual problem was.
                */
                fatalError("Unresolved error \(error), \(error.userInfo)")
            
        )
    

PS:这个项目我不是用Core Data开始的,是后来添加的

【问题讨论】:

【参考方案1】:

您的@FetchRequest 在初始化时没有NSManagedObjectContext。您正在使用此行创建它

let persistenceController = PersistenceController.shared

您的@FetchRequest 必须向下移动到ContentView 才能正常工作。

必须调用此行

 .environment(\.managedObjectContext, persistenceController.container.viewContext)

初始化包含@FetchRequestView

【讨论】:

以上是关于如何让 SwiftUI 与 Core Data 一起工作(在启动项目后)?的主要内容,如果未能解决你的问题,请参考以下文章

在 SwiftUI 中将 @FetchRequest 与 Core Data 一起使用时修改 nil 排序行为

Swift之深入解析如何结合Core Data和SwiftUI

SwiftUI 将 Core Data 实体读入 []

SWIFTUI Core Data 传递数字

如何从存储在 Core Data SwiftUI 中的数据计算平均值

Swiftui: MacOS App: Fetching Core Data in ContentView OK,但是如何使用 AppDelegate 的结果呢?