【问题标题】:SwiftUI CoreData not saving / not detecting changesSwiftUI CoreData 未保存/未检测到更改
【发布时间】:2021-04-18 07:47:44
【问题描述】:

我有一个名为 Cart 的实体,但似乎无法从我的视图模型中保存新数据。

Persistence.swift

struct PersistenceController {
    static let shared = PersistenceController()

    static var preview: PersistenceController = {
        let result = PersistenceController(inMemory: true)
        let viewContext = result.container.viewContext
        for _ in 0..<10 {
            let newItem = Item(context: viewContext)
            newItem.timestamp = Date()
        }
        for _ in 0..<10 {
            let newCart = Cart(context: viewContext)
            newCart.menuName = "name"
            newCart.menuImg = "img"
            newCart.menuCode = "code"
        }
        do {
            try viewContext.save()
        } catch {
            let nsError = error as NSError
            fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
        }
        return result
    }()

    let container: NSPersistentContainer

    init(inMemory: Bool = false) {
        container = NSPersistentContainer(name: "Project")
        if inMemory {
            container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
        }
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
    }
    
    func save() {
        let context = container.viewContext

        if context.hasChanges {
            print("Found Changes")
            do {
                try context.save()
            } catch {
                print("ERROR")
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        } else {
            print("NO Changes")
        }
    }
}

MenuViewModel.swift

class MenuViewModel.swift: ObservableObject, MenuDetailService {
    @Environment(\.managedObjectContext) var managedObjectContext

    func addToCart() {
        let newCart = Cart(context: managedObjectContext)
        newCart.menuCode = menuCode
        newCart.menuName = menuName
        newCart.menuImg = menuImg
        PersistenceController.shared.save()
    }
}

ProjectApp.swift

@main
struct ProjectApp: App {
    @Environment(\.scenePhase) var scenePhase

    let persistenceController = PersistenceController.shared

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

持久性控制器 func save() 总是不打印任何更改,好像我使用不同的上下文?而且我不知道如何使用持久性控制器中的上下文来保存新数据。我该怎么做呢?非常感谢。

【问题讨论】:

  • 对不起什么是暂时的?我希望将其保存为 SQLlite,我正在关注本教程:hackingwithswift.com/quick-start/swiftui/…
  • 奇怪的是,即使在本教程中,保存函数的定义与您的示例中一样,但它使用 PersistenceController.shared.saveContext() 代替。可能是教程中的错误,或者您也可以尝试一下?
  • 您在哪里/如何调用 addToCart?
  • 进一步检查,您不能在视图模型类中使用@Environment,它只能从View 舒适的类型中访问。所以使用依赖注入或通过持久化控制器访问托管上下文。
  • @JoakimDanielson 感谢您的回答,是的,我不知道如何通过持久性控制器访问托管上下文,尝试了很多方法但返回错误。原来这就像下面的lorem ipsum的答案。谢谢队友!

标签: swift core-data swiftui


【解决方案1】:
//Remove the `.swift` 
class MenuViewModel: ObservableObject, MenuDetailService {
    //@Environment does not work well outside of a struct :View . Updates are unreliable
    var managedObjectContext = PersistenceController.shared.container.viewContext
    // You need to pass the variables somehow to the new object when you call the method from the `View`
    func addToCart(menuCode: String, menuName: String, menuImg: UIImage) {
        let newCart = Cart(context: managedObjectContext)
        newCart.menuCode = menuCode
        newCart.menuName = menuName
        newCart.menuImg = menuImg
        PersistenceController.shared.save()
    }
}

【讨论】:

  • 非常感谢!奇迹般有效。这么简单的解决方案,真的不知道如何使用viewContext,你只是节省了我的一天
【解决方案2】:

我不确定那个教程,我还没有研究过,但是因为我已经在 SwiftUI 中使用过 CoreData,所以我什么都没看到:

let newCart = Cart(context: managedObjectContext)
newCart.menuCode = menuCode
newCart.menuName = menuName
newCart.menuImg = menuImg
PersistenceController.shared.save()

我所期望的是,您将那里的最后一行替换为:

do {
    try managedObjectContext.save()
} catch {
    print(error.localizedDescription)
}

【讨论】:

    猜你喜欢
    • 2017-02-18
    • 1970-01-01
    • 2012-03-18
    • 2015-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多