Как редактировать и переопределять CoreData в подробном представлении с помощью SwiftUI

Я работаю над системой управления пациентами, в которой мне нужно ввести всю необходимую информацию о пациенте и внести ее в список, сохранить и отредактировать, если это необходимо. Мне удалось сохранить их, перечислить и отобразить, когда я перехожу в подробное представление, но я не могу их редактировать и сохранять новую информацию поверх старой.

Я изучил все возможные ответы, чтобы решить эту проблему, и самое близкое, что я пришел, - это создание дубликата файла пациента.

Вот мой код (атрибуты на французском)

Файл списка пациентов:

  struct PatientList: View {
    @Environment(\.managedObjectContext) var moc
    @FetchRequest(entity: PatientInfo.entity(), sortDescriptors: [
        NSSortDescriptor(keyPath: \PatientInfo.nom, ascending: true),
        NSSortDescriptor(keyPath: \PatientInfo.prenom, ascending: true)])
    var patients: FetchedResults<PatientInfo>

    @State private var showingAddScreen = false

    var body: some View {
        NavigationView {
            List {
                ForEach(patients, id: \.self) { patient in
                    NavigationLink(destination: PatientDetail(patients: patient))
                    {
                        VStack{
                            HStack{
                                Text(patient.nom ?? "Inconnu")
                                Text(patient.prenom ?? "Inconnu")
                            }
                        }

                    }
                }
                .onDelete(perform: deletePatients)
            }
            .navigationBarTitle("Patients")
            .navigationBarItems(leading: EditButton(), trailing:
                    Button(action: {
                        self.showingAddScreen.toggle()
                    }) {
                        Image(systemName: "plus")
                }
            )
            .sheet(isPresented: $showingAddScreen) {
                AddNewPatient().environment(\.managedObjectContext, self.moc)
            }

            }


        }
    func deletePatients(at offsets: IndexSet) {
                for offset in offsets {
                    let patient = patients[offset]
                    moc.delete(patient)
                }
                try? moc.save()

        }


struct PatientList_Previews: PreviewProvider {
    static var previews: some View {
        PatientList()
    }
}
}

Файл AddNewPatient:

    struct AddNewPatient: View {

    @Environment(\.managedObjectContext) var moc
    @Environment(\.presentationMode) var presentationMode

    @State private var nom = ""
    @State private var prenom = ""
    @State private var ddn = Date()
    @State private var adresse = ""
    @State private var codepostal = ""
    @State private var ville = ""
    @State private var province = ""
    @State private var numerotelephone = "000-000-0000"
    @State private var dernierexamen = Date()



    var body: some View {
        NavigationView {
            Form {
                Section {
                    TextField("Nom", text: $nom)
                    TextField("Prénom", text: $prenom)
                }
                DatePicker("Date de naissance", selection: $ddn, displayedComponents: .date)

                Section {
                    TextField("Adresse", text: $adresse)
                    TextField("Code Postal", text: $codepostal)
                    TextField("Ville", text: $ville)
                    TextField("Province", text: $province)
                }
                Section {
                    TextField("Numéro de téléphone", text: $numerotelephone).keyboardType(.numberPad)
                }
                DatePicker("Dernier examen", selection: $dernierexamen, displayedComponents: .date)
                Section {
                    Button("Enregistrer") {
                        let newPatient = PatientInfo(context: self.moc)
                        newPatient.nom = self.nom
                        newPatient.prenom = self.prenom
                        newPatient.ddn = self.ddn
                        newPatient.adresse = self.adresse
                        newPatient.codepostal = self.codepostal
                        newPatient.ville = self.ville
                        newPatient.province = self.province
                        newPatient.numerotelephone = self.numerotelephone
                        newPatient.dernierexamen = self.dernierexamen

                        try? self.moc.save()
                        self.presentationMode.wrappedValue.dismiss()
                    }
            }
        }
        .navigationBarTitle("Nouveau Patient")
        .navigationBarItems(leading: EditButton())
    }
}

    struct AddNewPatient_Previews: PreviewProvider {
        static var previews: some View {
            AddNewPatient()
        }
    }
    }

Файл сведений о пациенте:

    struct PatientDetail: View {
    @Environment(\.managedObjectContext) var moc
    @Binding var patients: PatientInfo


    @State private var showingEditScreen = false




    var body: some View {
        NavigationView{
            Form{

                Section{
                    Text(self.patients.nom ?? "Nom")
                    Text(self.patients.prenom ?? "Prénom")
                    }

                Section{
                    Text(self.patients.adresse ?? "Adresse")
                    }

                Section{
                    Text(self.patients.codepostal ?? "Code Postal")
                    }
                Section{
                    Text(self.patients.ville ?? "Ville")
                }
                Section{
                    Text(self.patients.province ?? "Province")
                }
                Section{
                    Text(self.patients.numerotelephone ?? "000-000-0000")
                }


            }

        }
        .navigationBarTitle(Text(patients.nom ?? "Inconnu"), displayMode: .inline)
        .navigationBarItems(trailing: Button(action: { self.showingEditScreen.toggle()

        }) {
            Image(systemName: "square.and.pencil")
        }
    )
            .sheet(isPresented: $showingEditScreen) {
                EditPatientView(patients: self.patients).environment(\.managedObjectContext, self.moc)
            }
    }

struct PatientDetail_Previews: PreviewProvider {
    static let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
    static var previews: some View {
        let patients = PatientInfo(context: moc)
        patients.nom = "Amchou"
        patients.prenom = "Hicham"
        patients.ddn = Date()
        patients.adresse = "7580 Francois Chartrand"
        patients.codepostal = "H7A 3Z9"
        patients.ville = "Laval"
        patients.province = "Québec"
        patients.numerotelephone = "000-000-0000"
        patients.dernierexamen = Date()
        return NavigationView {
            PatientDetail(patients: PatientInfo)
        }
    }
}
}

и файл EditPatientView:

struct EditPatientView: View {

    @Environment(\.presentationMode) var presentationMode
    @Environment(\.managedObjectContext) var moc

    @ObservedObject var patients : PatientInfo


     @State private var nom = ""
     @State private var prenom = ""
     @State private var ddn = Date()
     @State private var adresse = ""
     @State private var codepostal = ""
     @State private var ville = ""
     @State private var province = ""
     @State private var numerotelephone = "000-000-0000"
     @State private var dernierexamen = Date()

    var body: some View {
        NavigationView {
            Form {
                Section {
                    TextField("Nom", text: self.$nom)
                    TextField("Prénom", text: self.$prenom)
                }
                Section {
                DatePicker("Date de naissance", selection: self.$ddn, displayedComponents: .date)
                }
                Section {
                    TextField("Adresse", text: self.$adresse)
                    TextField("Code Postal", text: self.$codepostal)
                    TextField("Ville", text: self.$ville)
                    TextField("Province", text: self.$province)
                }
                Section {
                    TextField("Numéro de téléphone", text: self.$numerotelephone).keyboardType(.numberPad)
                }
                DatePicker("Dernier examen", selection: self.$dernierexamen, displayedComponents: .date)
                Section {
                    Button("Enregistrer") {
                        let newPatient = PatientInfo(context: self.moc)
                        newPatient.nom = self.nom
                        newPatient.prenom = self.prenom
                        newPatient.ddn = self.ddn
                        newPatient.adresse = self.adresse
                        newPatient.codepostal = self.codepostal
                        newPatient.ville = self.ville
                        newPatient.province = self.province
                        newPatient.numerotelephone = self.numerotelephone
                        newPatient.dernierexamen = self.dernierexamen

                        try? self.moc.save()
                        self.presentationMode.wrappedValue.dismiss()
                    }
            }
        }
        .navigationBarTitle("Patient")

    }
}
}


struct EditPatientView_Previews: PreviewProvider {
    static var previews: some View {
        EditPatientView(patients: PatientInfo())
    }
}

(Надеюсь, это не слишком много информации. Публикация впервые)


person AMchou    schedule 18.05.2020    source источник


Ответы (1)


В EditPatientView у вас есть доступ к пациенту для редактирования. Почему бы не отредактировать это вместо создания нового пациента? Нравиться:

struct EditPatientView: View {
    @ObservedObject var patient : PatientInfo
    @Environment(\.managedObjectContext) var managedObjectContext

    var body: some View {
        Form {
            TextField("Name", text: $patient.name ?? "")
        }
        .onDisappear {
            try? self.managedObjectContext.save()
        }
    }
}

Проблема в том, что привязки TextField могут быть необязательными, но поля Core Data необязательны.

Это удобное расширение от https://stackoverflow.com/a/61002589/128083 делает свое дело:

func ?? <T>(lhs: Binding<T?>, rhs: T) -> Binding<T> {
    Binding(
        get: { lhs.wrappedValue ?? rhs },
        set: { lhs.wrappedValue = $0 }
    )
}

В моем SwiftUIPlayground также есть пример Core Data, демонстрирующий это..

person Ralf Ebert    schedule 18.05.2020
comment
Это полностью решило мою проблему. Я все пытался понять, почему это не сработает, а потом получил привязку (извините, я новичок во всем этом). Прошла через API, и это не помогло. Я чувствую облегчение. Спасибо большое!! - person AMchou; 19.05.2020