Published/Observed var 未在视图 swiftui 中更新 w/ 调用的函数
Published/Observed var not updating in view swiftui w/ called function
努力在 swiftui 中得到一个简单的例子和 运行:
- 加载默认列表视图(工作)
- 单击启动 picker/filtering 选项的按钮(有效)
- select 选项,然后单击按钮关闭并使用 selected 选项调用函数(调用正常)
- 显示新的对象列表return来自调用(不工作)
我卡在 #4 上,returned 查询没有进入视图。我怀疑我在步骤 #3 中进行调用时正在创建一个不同的实例,但这对我来说没有意义 where/how/why 这很重要。
我试着简化了一些代码,但还是有点,很抱歉。
感谢任何帮助!
带 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() 文件,以及 return 特定结果的可选函数:
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([=13=])
}
}
Spacer()
Button(action: {
self.query.filteredQuery(category: selectedCuisineType, glutenFree: gfSelected)
self.presentationMode.wrappedValue.dismiss()
}, label: {
Text( "apply filters")
})
}
.padding()
}
}
我怀疑问题是因为您没有在 TestView
和 CuisineTypePicker
之间共享 Query
的同一个实例。因此,当您对 CuisineTypePicker
中包含的实例启动新的 Firebase 查询时,结果永远不会反映在主视图中。
这是一个如何解决这个问题的例子(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([=10=])
}
}
Spacer()
Button(action: {
self.query.filteredQuery(category: selectedCuisineType, glutenFree: gfSelected)
self.presentationMode.wrappedValue.dismiss()
}, label: {
Text( "apply filters")
})
}
}
努力在 swiftui 中得到一个简单的例子和 运行:
- 加载默认列表视图(工作)
- 单击启动 picker/filtering 选项的按钮(有效)
- select 选项,然后单击按钮关闭并使用 selected 选项调用函数(调用正常)
- 显示新的对象列表return来自调用(不工作)
我卡在 #4 上,returned 查询没有进入视图。我怀疑我在步骤 #3 中进行调用时正在创建一个不同的实例,但这对我来说没有意义 where/how/why 这很重要。
我试着简化了一些代码,但还是有点,很抱歉。
感谢任何帮助!
带 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() 文件,以及 return 特定结果的可选函数:
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([=13=])
}
}
Spacer()
Button(action: {
self.query.filteredQuery(category: selectedCuisineType, glutenFree: gfSelected)
self.presentationMode.wrappedValue.dismiss()
}, label: {
Text( "apply filters")
})
}
.padding()
}
}
我怀疑问题是因为您没有在 TestView
和 CuisineTypePicker
之间共享 Query
的同一个实例。因此,当您对 CuisineTypePicker
中包含的实例启动新的 Firebase 查询时,结果永远不会反映在主视图中。
这是一个如何解决这个问题的例子(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([=10=])
}
}
Spacer()
Button(action: {
self.query.filteredQuery(category: selectedCuisineType, glutenFree: gfSelected)
self.presentationMode.wrappedValue.dismiss()
}, label: {
Text( "apply filters")
})
}
}