Изменения в SwiftUI FetchRequest не вызывают обновление представления? - PullRequest
4 голосов
/ 12 октября 2019

Использование оболочки FetchRequest и изменение данных полученных результатов внутри представления. Это работает при первой загрузке представления, которое обновляется при каждом внесенном изменении.

Проблема в том, что если я отошел от представления и вернулся снова, изменения для получения данных запроса перестали обновлять представление. Единственный способ увидеть изменения - это снова перейти назад и назад.

Я печатаю запрос на выборку, и изменения в данных работают, что объясняет, почему, если я возвращаюсь назад, вид снова отображается правильно, но представление не обновляется при изменении этих данных в представлении.

Это ошибка или я что-то делаю неправильно?

У меня есть представление библиотеки, в котором отображаются все журналы, впервый раздел представляет собой текстовое поле, позволяющее добавить новый журнал, во втором разделе - список всех журналов, которые можно выбрать, чтобы установить флажок рядом с ними.

Добавление новых журналов и их выбор работают в первую очередь. время .. Очень странно, что они перестают работать, если я ухожу и возвращаюсь.


struct LibraryView: View {

    // MARK: - PROPERTIES
    @Environment(\.managedObjectContext) var context


    @FetchRequest(
      //  entity: Journal.entity(),
        sortDescriptors: [NSSortDescriptor(keyPath: \Journal.name, ascending: true)],
        animation: .default
    ) var journals: FetchedResults<Journal>


    @State private var name = ""


    // MARK: - INITIAL VIEW -
    var body: some View {

        Form {

            Section(header: Text("New Journal")) {
                HStack {

                    TextField("Name", text: $name, onCommit: {
                        let newJournal = Journal(context: self.context)
                        newJournal.name = self.name
                        try? self.context.save()
                        self.name = ""
                    })

                    Button(action: { print("ACTION") }) {
                        Image(systemName: "plus.circle.fill")
                    }
                }
            }

            Section(header: Text("Journals")) {
                ForEach(journals) { journal in
                    Button(action: {
                        journal.isSelected.toggle()
                        try? self.context.save()

                    }) {
                        HStack {
                            Text(journal.name)
                            Spacer()
                            if journal.isSelected {
                                Image(systemName: "circle.fill")
                            }
                        }
                    }
                }
            }

        }.navigationBarTitle("Library")
    }
}

Журнал представляет собой простую базовую модель данных:


import Foundation
import CoreData

public class Journal: NSManagedObject, Identifiable {

    @NSManaged public var name: String
    @NSManaged public var isSelected: Bool

}

Я перехожу к библиотекеВид из вкладки Вид с навигационной ссылкой на панели навигации:


struct JournalView: View {

    // MARK: - PROPERTIES
    @State private var presentFiltersView = false

    // MARK: - INITIAL VIEW -
    var body: some View {
        NavigationView {
            Text("Journal")
                .navigationBarTitle("Journal")
                .navigationBarItems(
                    leading: NavigationLink(destination: LibraryView()) {
                        Text("Library")
                    },
                    trailing: Button(action: { self.presentFiltersView = true }) {
                        Text("Filters")
                    })
        }.sheet(isPresented: $presentFiltersView) { Text("Filters") }
    }
}

Я попытался удалить навигационную ссылку из элемента навигационной панели,и используя его как стандартную навигационную ссылку строки списка, результаты совпадают.

Ответы [ 3 ]

1 голос
/ 04 ноября 2019

Есть такая же проблема. NavigationLink немедленно создает экземпляр назначения. Как только я изменил это в ленивую оценку представления, это начинает работать для меня. Но это все еще выглядит как обходной путь.

struct LazyView<Content: View>: View {
    let build: () -> Content
    init(_ build: @autoclosure @escaping () -> Content) {
        self.build = build
    }
    var body: Content {
        build()
    }
}

См .: https://www.objc.io/blog/2019/07/02/lazy-loading/

NavigationLink(destination: LazyView(LibraryView()))

1 голос
/ 06 ноября 2019

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

До:

.navigationBarItems(leading:
    NavigationLink(
        destination: MyView(),
        label: {
    Text("MyView")
}))

После:

NavigationLink(
    destination: MyView(),
    isActive: $isActive,
    label: {
        EmptyView()
})

.navigationBarItems(leading:
    Button(
        action: self.isActive = true,
        label: {
    Text("My View")
}))

1 голос
/ 14 октября 2019

Отличный вопрос, у меня такая же проблема. Простой .onAppear () поможет, но я не могу понять, как .update () новый @ FetchRequest.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...