ios 修改coreData实体后视图未重绘-可能存在错误?

8i9zcol2  于 2023-03-24  发布在  iOS
关注(0)|答案(1)|浏览(162)

所以我会诚实,我发现了这个视图模型的想法在线创建或加载一个coredata实体在一个新的上下文中,然后保存结果.本质上,当我想编辑一个对象时,呈现的工作表加载有问题的对象,但父视图不重新加载以反映变化.即使视图模型中的对象类型是@Published,我正在CHANGING和SAVING上下文...
这可能是一个bug。
主视图编码

struct MainListView: View {
    
    //Bring in coreData singleton instance
    var provider = ContactsProvider.instance
     
//    //isShowing for sheet - defuct for edit button
//    @State private var isShowing = false
    @State private var orgToEdit: OrgEntity?
    
    //Fetching and assigning to orgEntity(s)  variable
    @FetchRequest(fetchRequest: OrgEntity.all()) private var orgEntitys
    
    var body: some View {
        NavigationStack {
            
            List {
                ForEach(orgEntitys) { org  in
                    NavigationLink(destination: OrgEntityDetailView(orgEntity: org)) {
                        MainListRow(orgEntity: org)
                            .swipeActions(allowsFullSwipe: true) {
                                //Buttons for delete / edit
                                Button(role: .destructive) {
                                    do {
                                        try provider.deleteOrg(org, context: provider.newContext)
                                    } catch {
                                        print("\(error)")
                                    }
                                } label: {
                                    Label("Delete", systemImage: "trash")
                                }
                                .tint(.red)
                                Button {
                                    orgToEdit = org
                                } label: {
                                    Label("Edit", systemImage: "pencil")
                                }
                                .tint(.orange)
                            }
                        
                    }
                }
            }
            .listStyle(.insetGrouped )
            .navigationTitle("My Map")
            .toolbar {
                ToolbarItem(placement: .primaryAction) {
                    Button {
                        orgToEdit = .empty(context: provider.newContext)
                    } label: {
                        Image(systemName: "plus")
                            .font(.title2)
                    }
                }
                ToolbarItem(placement: .navigationBarLeading) {
                    Button {
                        
                    } label: {
                        Image(systemName: "map")
                    }

                }
            }
            .sheet(item: $orgToEdit, onDismiss: {
                orgToEdit = nil
            }, content: { org in    //passing in this closure to the view
                NavigationStack {
                    CreateOrgView(vm: .init(provider: provider, orgEntity: org ))
                }
            })
        
        }
    }
}

查看型号代码

import Foundation
import CoreData

class EditOrgViewModel: ObservableObject {
    
    
    @Published var orgEntity: OrgEntity
    
    
    private let context: NSManagedObjectContext
    private let provider: ContactsProvider
    

    let isNew: Bool
    
  
    init(provider: ContactsProvider, orgEntity: OrgEntity? = nil) {
        //set context to new background context
        self.provider = provider
        self.context = provider.newContext
        if let orgEntity,   
           let existingContactCopy =  provider.orgExists(orgEntity, in: context) {
            self.orgEntity = existingContactCopy
            self.isNew = false
        } else {
            self.orgEntity = OrgEntity(context: self.context)
            self.isNew = true
        }
            
    }
    
    func save() throws {
            try provider.persist(in: context)
        }
    
}

提供者代码:Exists()和保存()函数

import Foundation
import CoreData
import SwiftUI

class ContactsProvider {
    
    //creating a singleton?
    static let instance: ContactsProvider = ContactsProvider()
    
    //Create the container of type NSpersistContainer
    let persistentContainer: NSPersistentContainer
    
    //computed property for viewContext - assuming for safety
    var viewContext: NSManagedObjectContext {
        persistentContainer.viewContext
    }
    
    //computed property for new context - used when editing or adding entities
    var newContext: NSManagedObjectContext {
        persistentContainer.newBackgroundContext()
    }
    
    private init() {
        persistentContainer = NSPersistentContainer(name: "ContactsDataModel")
        //Using the extension below for previews - makes a path to build a new context - in memory
        if EnvironmentValues.isPreview {
            persistentContainer.persistentStoreDescriptions.first?.url = .init(filePath: "/dev/null")
        }
        persistentContainer.viewContext.automaticallyMergesChangesFromParent = true
        //auto saves any changes
        persistentContainer.loadPersistentStores { _, error in
            if let error {
                fatalError("Unable to load store with error: \(error )")
            }
        }
    }
    
    
    func orgExists(_ orgEntity: OrgEntity, in context: NSManagedObjectContext) -> OrgEntity? {
        try? context.existingObject(with: orgEntity.objectID) as? OrgEntity
        //try and find a org with the context passed in that matches ID - then return the org
        
    }
    
    func personExists(_ personEntity: PersonEntity, in context: NSManagedObjectContext) -> PersonEntity? {
        try? context.existingObject(with: personEntity.objectID) as? PersonEntity
    }
    
    func deleteOrg(_ orgEntity: OrgEntity, context: NSManagedObjectContext) throws {
        if let existingOrg = orgExists(orgEntity, in: context) {
            context.delete(existingOrg)
            //swift ui concurrency and async save the coredata
            Task(priority: .background) {
                try await context.perform {
                    try context.save()
                }
            }
        }
    }
    
    func deletePerson(_ personEntity: PersonEntity, context: NSManagedObjectContext) throws {
        if let existingPerson = personExists(personEntity, in: context) {
            context.delete(existingPerson)
            //swift ui concurrency and async save the coredata
            Task(priority: .background) {
                try await context.perform {
                    try context.save()
                }
            }
        }
    }
    
    func persist(in context: NSManagedObjectContext) throws {
        if context.hasChanges {
            try context.save()
        }
    }
    
    
}

//Checking to see if we are in a preview so we can make a custom context sandbox - from stackoverflow
// used to check for creating a context in memory
extension EnvironmentValues {
    static var isPreview: Bool {
        return ProcessInfo.processInfo.environment["XCODE_RUNNING _FOR_PREVIEWS"] == "1"
    }
}
bq3bfh9z

bq3bfh9z1#

在此找到:
当SwiftUI中相关实体发生变化时,如何更新@FetchRequest?
需要将行也更新为@observedobject
这里:
HackingSwift

相关问题