父视图向子视图发送 aFetchRequest
和 a的谓词过滤字符串Binding
以返回FetchedResults
计数。
过滤器字符串是@State
父视图的属性。对父项中过滤器字符串的更改会导致子项更新FetchRequest
.
如何让子视图更新Binding
它收到的新FetchedResults
计数?
请参阅代码注释以Child
了解我的尝试。
struct Parent: View {
@State private var filter = "" // Predicate filter
@State private var fetchCount = 0 // To be updated by child
var body: some View {
VStack {
// Create core data test records (Entity "Item" with a property named "name")
Button("Create Test Items") {
let context = PersistenceController.shared.container.viewContext
let names = ["a", "ab", "aab", "b"]
for name in names {
let item = Item(context: context)
item.name = name
try! context.save()
}
}
// Buttons to modify the filter to update the fetch request
HStack {
Button("Add") {
filter = filter + "a"
}
Button("Remove") {
filter = String(filter.prefix(filter.count-1 >= 0 ? filter.count-1 : 0))
}
Text("Filter: \(filter)")
}
Text("Fetch count in parent view (not ok): \(fetchCount)")
Child(filter: filter, fetchCount: $fetchCount)
Spacer()
}
}
}
struct Child: View {
@FetchRequest var fetchRequest: FetchedResults<Item>
@Binding var fetchCount: Int
init(filter: String, fetchCount: Binding<Int>) {
let predicate = NSPredicate(format: "name BEGINSWITH[c] %@", filter)
self._fetchRequest = FetchRequest<Item>(
entity: Item.entity(),
sortDescriptors: [],
predicate: filter.isEmpty ? nil : predicate
)
self._fetchCount = fetchCount
// self.fetchCount = fetchRequest.count // "Modifying state during view updates, this will cause undefined behavior"
}
var body: some View {
VStack {
Text("Fetch count in child view (ok): \(fetchRequest.count)")
.onAppear { fetchCount = fetchRequest.count } // Fires once, not whenever the predicate filter changes
// The ForEach's onAppear() doesn't update the count when the results are reduced and repeatedly updates for every new item in results
ForEach(fetchRequest) { item in
Text(item.name ?? "nil")
}
//.onAppear { fetchCount = fetchRequest.count }
}
}
}