Используя SwiftUI, Core Data и отношения один ко многим, почему список не обновляется при добавлении строки на стороне Many - PullRequest
1 голос
/ 30 марта 2020

У меня есть проект SwiftUI с Core Data. Модель данных - это простое одно-ко-многим и два основных представления, каждое из которых имеет текстовое поле вверху и кнопку для добавления нового элемента в представление списка ниже. Первая точка зрения - для Одной стороны отношения, а вторая - для Многих. Итак, NavigationLink в первом открывает второй и пропускает объект One. Казалось бы, довольно стандартные вещи. Методология создания One работает, и приведенный ниже список обновляется немедленно, когда контекст управляемого объекта сохраняет новый элемент. Но методология того же типа не обновляет sh список для стороны Many при просмотре на устройстве, хотя она отлично работает в симуляторе и окне предварительного просмотра. Данные, безусловно, сохраняются, потому что если вы вернетесь назад в сторону One, а затем повторно выберите ее, чтобы повторно загрузить представление «Много», он отобразит новый элемент в списке.

Я просмотрел множество учебных пособий, другие вопросы и т. Д. c. и не нашел причину для этого. Я делаю что-то не так в том, как я перехожу на сторону Множество, или я должен сделать что-то еще, чтобы пересмотреть sh взгляд только на Множество? Спасибо !!!

Полный проект доступен по адресу https://github.com/fahrsoft/OneToManyTest

Из ContentView, показывая одну сторону (примечание: OneView - это простое представление, которое принимает объект и показывает текст. То же самое для ManyView.):

struct ContentView: View {
@Environment(\.managedObjectContext) var moc
@FetchRequest(entity: One.entity(), sortDescriptors: []) var ones: FetchedResults<One>

@State private var newName = ""
@State var isNavTitleHidden = true

var body: some View {
    NavigationView {
        VStack {
            HStack {
                TextField("New One", text: self.$newName)
                Spacer()
                Button(action: {
                    let newOne = One(context: self.moc)
                    newOne.name = self.newName
                    self.newName = ""
                    try? self.moc.save()
                }) {
                    Image(systemName: "plus.circle.fill")
                        .foregroundColor(.green)
                        .frame(width: 32, height: 32, alignment: .center)
                }
            }
            .padding(.top)
            .padding(.horizontal)

            List {
                Section(header: Text("Ones")) {
                    ForEach(self.ones, id:\.self) { (one:One) in
                        NavigationLink(destination: OneDetailView(one: one, isNavTitleHidden: self.$isNavTitleHidden).environment(\.managedObjectContext, self.moc)) {
                            OneView(one: one).environment(\.managedObjectContext, self.moc)
                        }
                    }

                    .onDelete { indexSet in
                        let deleteOne = self.ones[indexSet.first!]
                        self.moc.delete(deleteOne)
                        do {
                            try self.moc.save()
                        } catch {
                            print(error)
                        }
                    }
                }
            }
        }
        .navigationBarTitle(Text("Ones List"))
        .navigationBarHidden(self.isNavTitleHidden)
        .onAppear {
            self.isNavTitleHidden = true
        }
    }
}}

Из OneDetailView, показывающего сторону Many:

struct OneDetailView: View {
@Environment(\.managedObjectContext) var moc

@ObservedObject var one: One

@State private var newManyAttribute = ""
@Binding var isNavTitleHidden: Bool

var body: some View {
    VStack {
        HStack {
            TextField("New Many", text: self.$newManyAttribute)
            Spacer()
            Button(action: {
                let newMany = Many(context: self.moc)
                newMany.attribute = self.newManyAttribute
                self.newManyAttribute = ""
                self.one.addToMany(newMany)
                try? self.moc.save()
            }) {
                Image(systemName: "plus.circle.fill")
                    .foregroundColor(.green)
                    .frame(width: 32, height: 32, alignment: .center)
            }
        }
        .padding(.top)
        .padding(.horizontal)

        List {
            Section(header: Text("Manys")) {
                ForEach(self.one.manyArray, id: \.self) { many in
                    ManyView(many: many).environment(\.managedObjectContext, self.moc)
                }
            }
        }
    }
    .navigationBarTitle("\(self.one.wrappedName) Details")
    .onAppear {
        self.isNavTitleHidden = false
    }
}}

1 Ответ

0 голосов
/ 10 апреля 2020

Единственное, что я мог придумать, чтобы сделать его прилично хорошо работающим, - это создать новый запрос FetchRequest для множества элементов, используя выбранный элемент в предикате. Добавление FetchRequest и init к началу OneDetailView позволяет обновлять список.

struct OneDetailView: View {
@Environment(\.managedObjectContext) var moc

@ObservedObject var one: One

@State private var newManyAttribute = ""
@Binding var isNavTitleHidden: Bool

@FetchRequest var manys: FetchedResults<Many>

init(one: One, isNavTitleHidden: Binding<Bool>) {
    self.one = one
    self._isNavTitleHidden = isNavTitleHidden
    var predicate: NSPredicate?
    predicate = NSPredicate(format: "one = %@", one)
    self._manys = FetchRequest(
        entity: Many.entity(),
        sortDescriptors: [],
        predicate: predicate
    )
}

var body: some View {
    VStack {
        HStack {
            TextField("New Many", text: self.$newManyAttribute)
            Spacer()
            Button(action: {
                let newMany = Many(context: self.moc)
                newMany.attribute = self.newManyAttribute
                self.newManyAttribute = ""
                self.one.addToMany(newMany)
                try? self.moc.save()
            }) {
                Image(systemName: "plus.circle.fill")
                    .foregroundColor(.green)
                    .frame(width: 32, height: 32, alignment: .center)
            }
        }
        .padding(.top)
        .padding(.horizontal)

        List {
            Section(header: Text("Manys")) {
                ForEach(self.manys, id: \.self) { many in
                    ManyView(many: many).environment(\.managedObjectContext, self.moc)
                }
            }
        }
    }
    .navigationBarTitle("\(self.one.wrappedName) Details")
    .onAppear {
        self.isNavTitleHidden = false
    }
}}
...