对 SwiftUI FetchRequest 的更改不会触发视图刷新?
Posted
技术标签:
【中文标题】对 SwiftUI FetchRequest 的更改不会触发视图刷新?【英文标题】:Changes to SwiftUI FetchRequest not triggering view refresh? 【发布时间】: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")
我已经尝试从导航栏项目中删除导航链接,并将其用作标准列表行导航链接,结果是相同的。
【问题讨论】:
【参考方案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")
))
【讨论】:
以上是关于对 SwiftUI FetchRequest 的更改不会触发视图刷新?的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI - 如何在 init 中使用 fetchRequest 更新数据
@FetchRequest 中的 SwiftUI 和动态 NSSortDescriptors
如何在 SwiftUI 中限制 FetchRequest 中的结果数
如果没有数据,带有 @FetchRequest (SwiftUI) 和 NSPredicate 的 CoreData 会崩溃