swiftui - 已发布/观察到的 var 未在视图 swiftui 中更新,带调用函数
问题描述
努力在 swiftui 中启动并运行一个简单的示例:
- 加载默认列表视图(工作)
- 单击启动选择器/过滤选项的按钮(工作)
- 选择选项,然后单击按钮以关闭并使用所选选项调用功能(通话正常)
- 显示从调用返回的新对象列表(不工作)
我被困在#4,返回的查询没有进入视图。我怀疑我在第 3 步中进行调用时创建了一个不同的实例,但这对我来说在哪里/如何/为什么重要是没有意义的。
我试图将代码简化一些,但还是有点,抱歉。
感谢任何帮助!
带有 HStack 的主视图和用于过滤的按钮:
import SwiftUI
import FirebaseFirestore
struct TestView: View {
@ObservedObject var query = Query()
@State var showMonPicker = false
@State var monFilter = "filter"
var body: some View {
VStack {
HStack(alignment: .center) {
Text("Monday")
Spacer()
Button(action: {
self.showMonPicker.toggle()
}, label: {
Text("\(monFilter)")
})
}
.padding()
ScrollView(.horizontal) {
LazyHStack(spacing: 35) {
ForEach(query.queriedList) { menuItems in
MenuItemView(menuItem: menuItems)
}
}
}
}
.sheet(isPresented: $showMonPicker, onDismiss: {
//optional function when picker dismissed
}, content: {
CuisineTypePicker(selectedCuisineType: $monFilter)
})
}
}
Query() 文件调用包含所有结果的基本查询,以及返回特定结果的可选函数:
import Foundation
import FirebaseFirestore
class Query: ObservableObject {
@Published var queriedList: [MenuItem] = []
init() {
baseQuery()
}
func baseQuery() {
let queryRef = Firestore.firestore().collection("menuItems").limit(to: 50)
queryRef
.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
self.queriedList = querySnapshot?.documents.compactMap { document in
try? document.data(as: MenuItem.self)
} ?? []
}
}
}
func filteredQuery(category: String?, glutenFree: Bool?) {
var filtered = Firestore.firestore().collection("menuItems").limit(to: 50)
// Sorting and Filtering Data
if let category = category, !category.isEmpty {
filtered = filtered.whereField("cuisineType", isEqualTo: category)
}
if let glutenFree = glutenFree, !glutenFree {
filtered = filtered.whereField("glutenFree", isEqualTo: true)
}
filtered
.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
self.queriedList = querySnapshot?.documents.compactMap { document in
try? document.data(as: MenuItem.self);
} ?? []
print(self.queriedList.count)
}
}
}
}
我在其中调用过滤查询的选择器视图:
import SwiftUI
struct CuisineTypePicker: View {
@State private var cuisineTypes = ["filter", "American", "Chinese", "French"]
@Environment(\.presentationMode) var presentationMode
@Binding var selectedCuisineType: String
@State var gfSelected = false
let query = Query()
var body: some View {
VStack(alignment: .center) {
//Buttons and formatting code removed to simplify..
}
.padding(.top)
Picker("", selection: $selectedCuisineType) {
ForEach(cuisineTypes, id: \.self) {
Text($0)
}
}
Spacer()
Button(action: {
self.query.filteredQuery(category: selectedCuisineType, glutenFree: gfSelected)
self.presentationMode.wrappedValue.dismiss()
}, label: {
Text( "apply filters")
})
}
.padding()
}
}
解决方案
我怀疑问题源于您没有Query
在您的TestView
和您的CuisineTypePicker
. 因此,当您对 中包含的实例启动新的 Firebase 查询时CuisineTypePicker
,结果永远不会反映在主视图中。
这是一个如何解决这个问题的示例(现在将 Firebase 代码替换为一些非异步示例代码):
struct MenuItem : Identifiable {
var id = UUID()
var cuisineType : String
var title : String
var glutenFree : Bool
}
struct ContentView: View {
@ObservedObject var query = Query()
@State var showMonPicker = false
@State var monFilter = "filter"
var body: some View {
VStack {
HStack(alignment: .center) {
Text("Monday")
Spacer()
Button(action: {
self.showMonPicker.toggle()
}, label: {
Text("\(monFilter)")
})
}
.padding()
ScrollView(.horizontal) {
LazyHStack(spacing: 35) {
ForEach(query.queriedList) { menuItem in
Text("\(menuItem.title) - \(menuItem.cuisineType)")
}
}
}
}
.sheet(isPresented: $showMonPicker, onDismiss: {
//optional function when picker dismissed
}, content: {
CuisineTypePicker(query: query, selectedCuisineType: $monFilter)
})
}
}
class Query: ObservableObject {
@Published var queriedList: [MenuItem] = []
private let allItems: [MenuItem] = [.init(cuisineType: "American", title: "Hamburger", glutenFree: false),.init(cuisineType: "Chinese", title: "Fried Rice", glutenFree: true)]
init() {
baseQuery()
}
func baseQuery() {
self.queriedList = allItems
}
func filteredQuery(category: String?, glutenFree: Bool?) {
queriedList = allItems.filter({ item in
if let category = category {
return item.cuisineType == category
} else {
return true
}
}).filter({item in
if let glutenFree = glutenFree {
return item.glutenFree == glutenFree
} else {
return true
}
})
}
}
struct CuisineTypePicker: View {
@ObservedObject var query : Query
@Binding var selectedCuisineType: String
@State private var gfSelected = false
private let cuisineTypes = ["filter", "American", "Chinese", "French"]
@Environment(\.presentationMode) private var presentationMode
var body: some View {
VStack(alignment: .center) {
//Buttons and formatting code removed to simplify..
}
.padding(.top)
Picker("", selection: $selectedCuisineType) {
ForEach(cuisineTypes, id: \.self) {
Text($0)
}
}
Spacer()
Button(action: {
self.query.filteredQuery(category: selectedCuisineType, glutenFree: gfSelected)
self.presentationMode.wrappedValue.dismiss()
}, label: {
Text( "apply filters")
})
}
}
推荐阅读
- r - 在 left_join R 中使用 paste0
- javascript - javascript数组的增量和减量
- python - 在客户端发送文本文件后,Python Socket Server 接收到乱码文本文件
- visual-studio-code - 使用 VsCode C++(Win10 SSH 连接到 Ubuntu 18.04)在右键单击或 F12 时不会出现“转到定义”
- java - java jar 的 hadoop jar 命令 - 性能评估
- html - 如何保持图像响应而不影响其他元素?
- php - 模态逻辑以避免重复
- php - 填写表格后如何显示“消息发送成功”
- javascript - 我怎样才能使重复的句子只显示一次?
- regex - 带有换行符的大文本中精确单词的延迟量词