更新的核心数据值未反映在 SwiftUI 列表中

Updated core data values not Reflecting in SwiftUI List

我有一个税 Create/Edit 视图和列表视图,视图模型 Class 作为 Observable 对象。

我从编辑视图更新视图模型 class 中核心数据的值,更新的值未反映在使用相同视图模型 class 的列表视图中。 列表视图仅在我返回其他屏幕并进入此列表屏幕屏幕或重新启动应用程序时更新

请多多指教

列表查看代码

struct TaxListView: View {
    
    @State var searchTerm:String = ""
    @State var isTaxSelected = false
    @State var seletedTax:TaxCodesList = TaxCodesList(businessId: "", taxID: "", taxName: "", taxRate: 0.0, taxtype: "", taxCodes: [TaxCodeList]())

    @ObservedObject var taxViewModel = TaxViewModel()
    @Environment(\.presentationMode) var mode
    
var body : some View {
    
    VStack{
        List{
            ForEach(taxViewModel.arrTaxCodes, id: \.taxID){ tax in
                TaxlistRow(tax: tax, selectedTax: $seletedTax, taxSelected: $isTaxSelected)
            }
        }
    }
    
}

查看模型Class

class TaxViewModel:ObservableObject {
    
    @Published var arrTaxCodes:[TaxCodesList] = []
    @Published var arrTempTaxCodes:[TaxCodesList] = []
    
    let context = PersistenceController.shared.container.viewContext
    
    func getTaxCodes(){
        let fetchRequest : NSFetchRequest<TaxCodes> = TaxCodes.fetchRequest()
            fetchRequest.predicate = NSPredicate(format: "businessId = %@", Constants.businessID ?? "")
        
        do {
            let result = try context.fetch(fetchRequest)
            arrTaxCodes.removeAll()
            for data in result {
                arrTaxCodes.append(TaxCodesList(responseObj: data))
            }
            arrTempTaxCodes = arrTaxCodes
            
        } catch  {
            print(error.localizedDescription)
        }
    }
    
    //MARK: Update Tax
    func updateTax(tax:TaxCodesList, completion:@escaping (Bool,String) -> Void) {
        
        let fetchRequest : NSFetchRequest<TaxCodes> = TaxCodes.fetchRequest()
        fetchRequest.predicate = NSPredicate(format: "taxID = %@", tax.taxID)
        
        do {
            let result = try context.fetch(fetchRequest)
            
            guard let objectToUpdate = result.first else {
                return
            }
            
            var taxCodesObj = [[String:Any]()]
            ///// assigning values to taxCodesObj 
 
            objectToUpdate.setValue(tax.taxName ,forKey: "taxName")
            objectToUpdate.setValue(tax.taxRate, forKey: "taxRate")
            objectToUpdate.setValue(tax.taxType, forKey: "taxType")
            objectToUpdate.setValue(["taxCodes":taxCodesObj], forKey: "taxCodes")
            
            do {
                try context.save()
                //Context.refreshAllObjects()
                completion(true,"Tax Updated Successfully")
            } catch {
                completion(true,error.localizedDescription)
                print(error.localizedDescription)
            }

        } catch  {
            completion(true,"TaxId not Found")
            print(error.localizedDescription)
        } 
    }   
}

编辑视图

struct CreateTaxView: View {

    ///// Some Variables
    
    @ObservedObject var taxViewModel:TaxViewModel
    
    @Environment(\.presentationMode) var mode
    
    func saveTax(){
        
        //// Codes to create tax Object
            taxViewModel.updateTax(tax: tax) { flag, msg in
                print(msg)
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
                    self.mode.wrappedValue.dismiss()
                })
            }   
        } 
    
    var body: some View {
        Form {
            Section {
                ///// Some Views
            }
            .onAppear{
                taxViewModel.getTaxCodes(Context: viewContext)
                if isFromUpdate && isInitialLoad {
                 /////Assign values to variables
                }
            }
        }
        .navigationBarTitle(Text(navTitle))
        .navigationBarItems(trailing: Button{
            saveTax()
        } label:{
            Text("Save")
        } )
            
    }
    
    func delete(at offsets:IndexSet){
        taxCodes.remove(atOffsets: offsets)
    }

TaxCodesList 结构

struct TaxCodesList{
    
    var businessId:String
    var taxID:String
    var taxName:String
    var taxRate: Double
    var taxType:String
    var taxCodes:[TaxCodeList]
    
    ////Init code
    

    //Initialize from core data object
    init(responseObj:TaxCodes){
        self.businessId = responseObj.businessId ?? ""
        self.taxID = responseObj.taxID ?? ""
        self.taxName = responseObj.taxName ?? ""
        self.taxRate = responseObj.taxRate
        self.taxType = responseObj.taxType ?? ""
        
        let payload = responseObj.taxCodes?["taxCodes"] as? [[String:Any]] ?? [[String:Any]()]
        var tempArr = [TaxCodeList]()
        tempArr.removeAll()
        for data in payload {
            if !(data["taxId"] as? String ?? "").isEmpty {
                tempArr.append(TaxCodeList(responseObj: data))
            }
        }
        self.taxCodes = tempArr
    }
    
}

我也错过了 TaxCodeList 的代码(没有“s”),但我想我发现了问题:在您的视图模型中,您正在从 CoreData 读取并传递 TaxCodes 实体到名为 TaxCodesListstruct(带有“s”)。然后,您的视图模型正在发布来自结构数组的更改。

您的视图正在读取来自 TaxCodesList 结构数组的数据,而不是来自 Core Data 对象的数据。结构无法发布更改,因此当您更改核心数据时您的视图无法更新 - 更改未到达视图。

你的代码有点长,我给你解决方案,但第一步是让你的观点阅读形成ObservableObject,可以是class 或直接的 Core Data 对象。根据您想要实现的目标,您可以将 TaxCodesList 变成 class,或者 - 我个人的偏好 - 将 TaxCodesList 变成核心数据实体并在这个新实体之间创建关系和 TaxCodes.

通话

getTaxCodes()

当你想看到更新时。

您的代码中没有任何部分在观察持久存储。您的列表不知道何时获取新值

您完全断开了 CoreData 与视图模型和结构的连接。如果你这样做是为了抽象而不是无意的,那很好,但你必须以某种方式听取商店的意见,这样你才能重新创建一切。

在视图中使用诸如 onChange 之类的东西可能会或可能不会在需要时提供更新。商店可以从许多不同的方向发生变化,您的抽象层将不会意识到。

This 可能会为您提供另一种聆听方式。

如果这是无意的模式,请直接使用 CoreData 对象,方法是用

包装它
@ObservedObject

这样您就可以进行更改并立即看到它们。

上面的 link 也有一个更直接的 CoreData 设置,并且有一个简单的

CoreDataPersistence

为任何对象完成所有繁重工作的对象。