CoreData не синхронизируется с моими списковыми представлениями в SwiftUI

#swift #swiftui

Вопрос:

Я изо всех сил пытаюсь научиться использовать основные данные и заставить их принудительно синхронизировать представление, используя @State. В основном я пытаюсь создать простое в использовании приложение, чтобы узнать, как все это работает вместе. Я могу добавить новый элемент в основные данные, но каким-то образом представление не обновляет список элементов в режиме реального времени, мне нужно остановить предварительный просмотр, а затем перестроить, чтобы мой новый элемент появился в списке.

Может кто-нибудь взглянуть на мой код, чтобы понять, что не так?

Я разделил свой код на 4 файла:

 import Foundation
import CoreData
import UIKit

class CoreDataStorage {
    
    lazy var persistentContainer: NSPersistentContainer = {
            let container = NSPersistentContainer(name: "StoriesFromFallacya")
            container.loadPersistentStores { description, error in
                if let error = error {
                    fatalError("Unable to load persistent stores: (error)")
                }
            }
            return container
        }()
    
    var context: NSManagedObjectContext {
      return  persistentContainer.viewContext
    }
    
    func fetchTaskList() -> [Dump] {
        
        let dumpList: [Dump]
        let fetchRequest: NSFetchRequest<CDDump> = CDDump.fetchRequest()
        if let rawDumPlist = try? context.fetch(fetchRequest){
            dumpList = rawDumPlist.compactMap({(rawDump:CDDump) -> Dump? in
                Dump(fromCoreDataObject: rawDump)
            })
        }else {
            dumpList = []
        }
        return dumpList
    }
    
    
    func addNewDump(dump: Dump){
        let newDump = CDDump(context: context)
        newDump.id = dump.id
        newDump.name = dump.name
        saveData()
    }
    
  
    
     func fetchCDDump(withId dumpId: UUID) -> CDDump?{
        let fetchRequest: NSFetchRequest<CDDump> = CDDump.fetchRequest()
        fetchRequest.predicate = NSPredicate(format: "id == %@",  dumpId as CVarArg)
        fetchRequest.fetchLimit = 1
        let fetchResult = try? context.fetch(fetchRequest)
        return fetchResult?.first
    }
    
    
    private func saveData(){
        if context.hasChanges {
            do {
                try context.save()
                
            }catch {
                print("Erreur pendant la sauvegarde CoreData: (error)")
            }
        }
    }
    
    
    
    func deleteDump(dumpID:UUID){
        if let dumpFound = fetchCDDump(withId: dumpID){
            self.context.delete(dumpFound)
            saveData()
        }else {
            print("Pas trouvé")
        }
    }
}

extension Dump {
    init?(fromCoreDataObject coreDataObject: CDDump){
        guard let id = coreDataObject.id, let name = coreDataObject.name else {
            return nil
        }
        self.id = id
        self.name = name
     
    }
}
 
  1. DumpManager
 import Foundation
import SwiftUI

class DumpManager: ObservableObject {
    
    let storage: CoreDataStorage = CoreDataStorage()
    
   @Published var dumpList: [Dump] 
    
    init(){
        dumpList = storage.fetchTaskList()
    }

    @discardableResult
     func addDump(dumpName: String) -> Dump {
        let newDump = Dump(name: dumpName)
        dumpList.append(newDump)
        storage.addNewDump(dump: newDump)
        return newDump
    }
    
     func deleteDump(withID dumpID:UUID) {
        if let indexDump = dumpList.firstIndex(where: {
            (dump) -> Bool in
            dump.id == dumpID
        }) {
            dumpList.remove(at: indexDump)
            storage.deleteDump(dumpID: dumpID)
        }
    }
  
}
 
  1. BrainDumpView
 import SwiftUI
import CoreData

struct BrainDumpView: View {

   
//    @ObservedObject var dumpManager: DumpManager = DumpManager()
    @State var theFuckingList = DumpManager().dumpList
    @State var taskManager = DumpManager()
   
 
    
    @State private var showingAddDumpView: Bool = false
//    @State var newDumpName: String
    
    var body: some View {
        NavigationView {
            VStack {
                VStack(alignment: HorizontalAlignment.leading){
                List{
                    ForEach(taskManager.dumpList) { dump in
                    Text(dump.name)
                }
                .onDelete(perform: deleteDump)
                .onTapGesture {
                    updateDump()
                }
            }
                Spacer()
        }
            }
            .navigationBarTitle(Text("Brain Dumps"))
            .navigationBarItems(trailing:
              Button(action:
                showingAddDump
            ) {
                Image(systemName: "plus")
                    .font(.largeTitle)
            }
            )
            }
       
        .sheet(isPresented: $showingAddDumpView, content: {
            NewDumpView(newDumpName: "", dumpList: $taskManager.dumpList)

                            })
       
    }
    func showingAddDump() {
        showingAddDumpView.toggle()
    }
//    func createNewDump() {
//        if newDumpName.count > 0 {
//            dumpManager.addDump(dumpName: newDumpName)
//        }
//        newDumpName = ""
//    }
    
    func deleteDump(offsets: IndexSet){
        taskManager.deleteDump(withID: taskManager.dumpList[offsets[offsets.startIndex]].id)
        }
    }

func updateDump(){
    
}

struct BrainDumpView_Previews: PreviewProvider {
 
    
    static var previews: some View {
        
      
        BrainDumpView()
    }
}
 
  1. NewDumpView
 import SwiftUI

struct NewDumpView: View {
    
  
    @Environment(.presentationMode) var presentationMode
    @ObservedObject var dumpManager: DumpManager = DumpManager()
    @State var taskManager = DumpManager()
    @State var newDumpName: String
    @Binding var dumpList: [Dump]
  
    var body: some View {
        NavigationView {
            VStack{
                Spacer()
                TextField("Dump", text: $newDumpName, onCommit: createNewDump)
                    
                    .padding()
                    .background(Color(UIColor.tertiarySystemFill))
                    .cornerRadius(9)
                    .font(.system(size: 24, weight: .bold, design: .default))
                    .navigationBarTitle("New Dump", displayMode: .inline)
                    .navigationBarItems(trailing:
                      Button(action: {
                        self.presentationMode.wrappedValue.dismiss()
                    }) {
                        Image(systemName: "xmark")
                    }
                    )
           
                Button(action: {
                               self.presentationMode.wrappedValue.dismiss()
                    createNewDump()
                             }) {
                               Text("Save")
                             }
            }
            
        }
        .padding()
                .navigationViewStyle(StackNavigationViewStyle())
                                    }
    
    func createNewDump() {
        if newDumpName.count > 0 {
            
            taskManager.addDump(dumpName: newDumpName)
        }
        newDumpName = ""
        self.presentationMode.wrappedValue.dismiss()
    }
                                    
}
 

Заранее большое спасибо, я уже несколько дней борюсь с этим :/

Комментарии:

1. Вы не наблюдаете за хранилищем или основными объектами данных. Я предлагаю вам просмотреть пример кода, предоставляемый при создании проекта. Вы пытаетесь применить MVC в SwiftUI, не понимая, как работает SwiftUI, наблюдение является ключевым. У вас в аренде 5 экземпляров вашего менеджера, ни один из них не знает, что делает другой. Вместо того, чтобы форсировать события, попробуйте изучить основные концепции с помощью учебных пособий Apple SwiftUI