在视图主体内显示查询值

时间:2019-11-29 17:28:38

标签: google-cloud-firestore swiftui

我要做什么::我想在用户登录应用后在“个人资料”视图上显示用户的姓名。目前,我已经使用Firebase Auth实施了登录。用户创建帐户时,会在Firestore的“用户”集合中创建一条记录,该记录记录名字和姓氏以及电子邮件地址。

我尝试过的事情:在“个人资料”视图上,我当前具有一个“ getUser”功能,用于检查用户是否已登录,然后匹配该用户的Firebase Auth电子邮件地址并对其进行匹配到Firestore中的记录。之所以有效,是因为我已经通过控制台中记录的内容检查了查询返回的信息。但是,我不知道如何获取“ fName”信息并将其显示在视图的正文中。

这是数据库结构和我当前代码的屏幕截图。

Firebase Auth

Firestore

import SwiftUI
import Firebase
import Combine
import FirebaseFirestore

struct ProfileView: View {

@EnvironmentObject var session: SessionStore
let db = Firestore.firestore()


func getUser() {
    session.listen()
    let query = db.collection("users").whereField("email", isEqualTo: session.session!.email!)
    query.getDocuments { (QuerySnapshot, err) in
        if let docs = QuerySnapshot?.documents {
            for docSnapshot in docs {
                print (docSnapshot.data())
            }
        }
    }
}



var body: some View {
    Group {
        if (session.session != nil) {
            NavigationView {
                VStack {
                    Text("Welcome back \(session.session!.email ?? "user")")
                    Spacer()
                    Button(action: session.signOut) {
                        Text("Sign Out")
                    }.padding(.bottom, 60)

                }
            } // end NavigationView
        } else {
            AuthView()
        }
    }.onAppear(perform: getUser)
}
}

2 个答案:

答案 0 :(得分:0)

我想您应该使用UserDefaults保存从Firestore返回的值

import UIKit


//your get user data logic here

let fName:String = <the first name retrieved from firestore>

// Get the standard UserDefaults as "defaults"
let defaults = UserDefaults.standard

// Save the String to the standard UserDefaults under the key, "first_name"
defaults.set(fName, forKey: "first_name")

并且在您的个人资料页面中,您应该获取该值

// you should have defaults initialized here
fnameToDisplay = defaults.string(forKey: "first_name")

答案 1 :(得分:0)

您好,我更喜欢制作一个ViewModel-NetworkManager类,它使ObservableObject更加舒适,并且在其中可以获取和获取数据,并且当它们完成加载后,它们将更新视图。让我向您展示一个示例,它如何工作:

如您所见,我在其中创建了一个NetworkManager扩展ObservableObject(因为我想在用户完成加载时得到通知),您可以看到var user带有@Published的注释,使用户观察到的情况以及何时有新的数据集将通知视图进行更新。您还可以看到我在init上加载了数据,因此此类初始化的第一时间将调用fetchData() func

class NetworkManager: ObservableObject {

    let url: String = "https://jsonplaceholder.typicode.com/todos/1"
    var objectWillChange = PassthroughSubject<NetworkManager, Never>()

    init() {
        fetchData()
    }

    @Published var user: User? {
        didSet {
            objectWillChange.send(self)
            print("set user")
        }
    }
    func fetchData() {
        guard let url = URL(string: url) else {return}
        print("fetch data")
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            guard error == nil else {return}
            print("no error")
            guard let data = data else {return}
            print("data is valid")
            let user = try! JSONDecoder().decode(User.self, from: data)
            DispatchQueue.main.async {
                self.user = user
            }
        }.resume()
    }
}

ContentView是我要放置用户数据或我声明的@ObservedObject var networkManager的信息的地方,原因是它扩展了ObservableObject并放置了视图并传递了用户

struct ContentView: View {
    @ObservedObject var networkManager = NetworkManager()
    var body: some View {
        VStack {
            DetailsView(user: networkManager.user)
        }
    }
}

struct DetailsView: View {
    var user: User?
    var body: some View {
        VStack {
            Text("id: \(user?.id ?? 0)")
            Text("UserID: \(user?.userId ?? 0 )")
            Text("title: \(user?.title ?? "Empty")")
        }
    }
}

class User: Decodable, ObservableObject {
    var userId: Int = 0
    var id: Int = 0
    var title: String = ""
    var completed: Bool = false
}
  

PS:我没有正确解开物体,请考虑一下   您没有任何零例外