所以我会诚实,我发现了这个视图模型的想法在线创建或加载一个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"
}
}
1条答案
按热度按时间bq3bfh9z1#
在此找到:
当SwiftUI中相关实体发生变化时,如何更新@FetchRequest?
需要将行也更新为@observedobject
这里:
HackingSwift