【问题标题】:Changes to SwiftUI FetchRequest not triggering view refresh?对 SwiftUI FetchRequest 的更改不会触发视图刷新?
【发布时间】:2019-10-12 18:49:56
【问题描述】:

使用 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") }
    }
}

我已经尝试从导航栏项目中删除导航链接,并将其用作标准列表行导航链接,结果是相同的。

【问题讨论】:

    标签: ios swift swiftui


    【解决方案1】:

    有同样的问题。 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()))

    【讨论】:

    • 一定要试一试。谢谢!
    • 这完美无瑕。为什么他们立即实例化目的地是一个谜。
    • 提前实例化目标可在单击时提供更快的响应。在幕后使用 Combine 框架可以让他们为此使用其他核心。另一方面,它引入了我们都遇到的其他问题。
    • 谢谢!唯一对我有用的东西。 :)
    【解决方案2】:

    我想我明白为什么会这样了。问题是我导航到视图的方式。在导航栏项目中有一个导航链接是原因。相反,我将导航链接单独移到了外部,并将其替换为控制导航链接活动状态的按钮。 Fetch Request 现在似乎可以正常工作了。

    之前:

    .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")
    }))
    
    

    【讨论】:

      猜你喜欢
      • 2020-03-09
      • 1970-01-01
      • 1970-01-01
      • 2022-01-07
      • 2021-01-17
      • 2020-04-05
      • 1970-01-01
      • 2022-12-15
      • 2012-09-04
      相关资源
      最近更新 更多