我正在 iOS 上开发移动应用程序,需要在用户单击按钮时跟踪一些数据。但是,当我尝试根据官方文档获取数据时,什么也没有显示。这是我的片段:
import SwiftUI
import FirebaseStorage
import FirebaseCore
import FirebaseFirestore
struct Station_View: View {
@State private var showingAlert = false
var ref: Firestore!
var station_ : station
var food : [food] = []
var body: some View {
VStack(alignment: .leading, spacing: 10, content: {
VStack {
ForEach(station_.menu_items, id: \.self) { i in
Divider()
.frame(width: 400, height: 1)
.background(Color("Black"))
.padding(.vertical,0)
HStack {
VStack (alignment: .leading) {
Text(i.name + ", " + i.calories + "cal, protein: " + i.protein)
.font(.headline)
.foregroundColor(Color("Black"))
}.padding(.leading, 8)
Spacer()
if (Int(i.protein)! > 10) {
Button(action: {
// print("Button action")
////////// I retrieved data here //////////////////
let docRef = ref?.collection("users").document("7lqIqxc7SGPrbRhhQWZ0rdNuKnb2")
docRef?.getDocument { (document, error) in
if let document = document, document.exists {
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
print("Document data: \(dataDescription)")
} else {
print("Document does not exist")
}
}
////////// I retrieved data here //////////////////
self.showingAlert = true
}) {
HStack {
Image(systemName: "p.circle")
Text("+50xp")
}.padding(10.0)
.overlay(
RoundedRectangle(cornerRadius: 6.0)
.stroke(lineWidth: 2.0)
)
}
.alert(isPresented: $showingAlert) {
() -> Alert in
Alert(title: Text("Congratulations!"), message: Text("You had a protein meal, XP+50!"), dismissButton: .default(Text("OK")))
}
}
if (i.is_vegan) {
Button(action: {
// print("Button action")
////////// I retrieved data here //////////////////
let docRef = ref?.collection("users").document("7lqIqxc7SGPrbRhhQWZ0rdNuKnb2")
docRef?.getDocument { (document, error) in
if let document = document, document.exists {
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
print("Document data: \(dataDescription)")
} else {
print("Document does not exist")
}
}
////////// I retrieved data here //////////////////
self.showingAlert = true
}) {
HStack {
Image(systemName: "leaf")
Text("+50xp")
}.padding(10.0)
.overlay(
RoundedRectangle(cornerRadius: 6.0)
.stroke(lineWidth: 2.0)
)
}
.alert(isPresented: $showingAlert) {
() -> Alert in
Alert(title: Text("Congratulations!"), message: Text("You had a vegan meal, XP+50!"), dismissButton: .default(Text("OK")))
}
}
}
.padding(.init(top: 12, leading: 0, bottom: 12, trailing: 0))
}
}
} )
}
}
我该怎么做才能让它成真?我希望只更新一个键值对,而其他键值对在收集数据时保持不变。
首先,在使用 SwiftUI 时,您应该始终使用 ViewModel。起初这是一个奇怪的过渡,但它会让你的代码更容易理解和跟踪。这是基本结构。
class YourViewModel: ObservableObject {
@Published var isTrue = false
func isValueTrue(){
print(isTrue.description)
}
}
请注意,这里发生了一些事情ObservableObject
,@Published
本质上这意味着YourViewModel
可以使用已发布的属性或可以绑定到视图的属性来观察对象。要在视图中使用它,您可以这样做。
struct YourView: View {
//This is your ViewModel reference.
//Use is to bind all your details to the view with
//something like yourViewModel.firstName or $yourViewModel.firstName
@observedObject var yourViewModel = YourViewModel()
var body: some View {
Button("Change Bool") {
yourViewModel.isTrue.toggle()
yourViewModel.isValueTrue()
}
}
}
这是 MVVM 模式的基本结构,将为您节省大量的视图空间,使其更易于阅读和维护。通常,您将有一个单独的.swift
文件用于View
和ViewModel
尽量不要将它们组合起来,并尽可能多地抽象。
要回答最终的问题,您如何从 Firebase 检索数据并更新相同的数据?那么,答案如下,我将演示如何使用中的功能和属性ViewModel
,你可以Bind
对你的意见对其进行更新。
//These properties are a part of the VIEWMODEL and can be bound to the view
//Using yourViewModel.someProperty
@Published var firstName = ""
@Published var lastName = ""
@Published var email = ""
func fetchFirebaseData() {
guard let uid = Auth.auth().currentUser?.uid else {
print("Handle Error")
return
}
//Create Database Reference
let db = Firestore.firestore()
//Reference the collection and document. In this example
//I'm accessing users/someUserId
let fsUserProfile = db.collection("users").document(uid)
//Request the document
fsUserProfile.getDocument { (snapshot, err) in
if err != nil { return }
self.fetchImageFromURL(url: URL(string: snapshot?.get("profile_image_url") as? String ?? "")!)
self.firstName = snapshot?.get("first_name") as? String ?? ""
self.lastName = snapshot?.get("last_name") as? String ?? ""
self.email = snapshot?.get("email") as? String ?? ""
}
}
这是更新 Firebase 数据的简单方法。这是通过传递一个带有键的字典来处理的,键是字段和与之关联的值。警告:不要使用setData(...)
它会清除你在那里的所有其他东西。setData(...)
对于首次创建数据很有用,例如注册帐户、创建新条目等。
func updateFirebaseData(firstName: String) {
if let user = Auth.auth().currentUser {
let db = Firestore.firestore()
db.collection("users").document(user.uid).updateData(["first_name": firstName])
}
}
struct YourView: View {
@observedObject var yourViewModel = YourViewModel()
var body: some View {
VStack {
//Fetching Example
VStack {
Button("Fetch Data") {
yourViewModel.fetchFirebaseData()
}
Text(yourViewModel.firstName)
}
//Setting Example
VStack {
Button("Update Data") {
//You could have this "John" value, a property
//of your ViewModel as well, or a text input, or whatever
//you want.
yourViewModel.updateFirebaseData(firstName: "John")
}
}
}
}
}
请注意,在 SwiftUI 中工作时 MVVM 结构是多么干净,一旦你这样做了几天,它就会成为第二天性。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句