背景關系:我正在嘗試使用 firebase 身份驗證和 firestore 來獲取用戶的資料。我遇到的問題是在完全獲取資料之前顯示視圖,這顯然會導致應用程式崩潰。話雖如此,我在我的應用程式委托中使用 firebase 身份驗證偵聽器來確保用戶在獲取用戶資料之前已通過身份驗證(這也在應用程式委托中完成,如下所示)
應用程式委托片段
class AppDelegate: NSObject, UIApplicationDelegate {
var handle: AuthStateDidChangeListenerHandle?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
self.handle = Auth.auth().addStateDidChangeListener { (auth, user) in
if (user != nil){
print("UserAuthentication User authenticated in delegate")
DatabaseDelegate().getUserInfo(UID: user!.uid, withCompletionHandler: {
print("got user data")
})
} else {
print(" UserAuthentication User not authenticated in delegate")
try! Auth.auth().signOut()
}
}
return true
}
這是我正在查詢并希望在資料加載完成時監聽的資料庫代碼:
class DatabaseDelegate: ObservableObject {
@Published var userDataLoaded = Bool()
func getUserInfo(UID: String, withCompletionHandler completionHandler: @escaping () -> Void) {
database.collection("Users").document(UID).getDocument { (document, error) in
if let document = document, document.exists {
let data = document.data()!
guard let UID = data["UUID"] as? String else { return }
guard let Name = data["Name"] as? String else { return }
guard let PhoneNumber = data["PhoneNumber"] as? String else { return }
guard let StripeID = data["StripeID"] as? String else { return }
self.userDataLoaded = true
UserData.append(User(UID: UID, Name: Name, PhoneNumber: PhoneNumber, StripeID: StripeID, PurchasedContent: ["TEMP": true]))
completionHandler()
}
}
}
}
這是我想根據上面的 userDataLoaded 更新的 SwiftUI 視圖:
struct MainViewDelegate: View {
//MARK: VARIABLES
@State var showAnimation = true
@State var locationHandler = LocationHandler()
@ObservedObject var databaseDelegate = DatabaseDelegate()
init(){
//Check and enable user location
locationHandler.requestAuthorisation()
}
var body: some View {
VStack {
//Check if data has finished loading, if not, show loading. Listen for changes when the data is finished loading and then present the tab view when it is.
switch databaseDelegate.userDataLoaded {
case true:
TabView {
HomeView()
.tabItem {
Label("Home", systemImage: "house")
}
CheckoutView()
.tabItem {
Label("Services", systemImage: "bag")
}
SettingsView()
.tabItem {
Label("Settings", systemImage: "gearshape")
}
}
case false:
Text("Loading data")
}
}
}
}
先謝謝了。我是 swiftui 的新手(從 uikit 過渡),我花了太多時間試圖解決這個愚蠢的問題
uj5u.com熱心網友回復:
- 您正在使用 的兩個不同實體
DatabaseDelegate,一個在 AppDelegate 中,一個在 MainViewDelegate 中。布林值僅在應用程式委托的實體中更新。
將您的身份驗證偵聽器移動到您的 DatabaseDelegate 中。
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
return true
}
}
class DatabaseDelegate: ObservableObject {
@Published var userDataLoaded = false
private var handle: AuthStateDidChangeListenerHandle?
init() {
self.handle = Auth.auth().addStateDidChangeListener { (auth, user) in
// .. etc
self.getUserInfo(...)
}
}
private func getUserInfo(UID: String, withCompletionHandler completionHandler: @escaping () -> Void) {
database.collection("Users").document(UID).getDocument { (document, error) in
// .. etc
self.userDataLoaded = true
}
}
}
- 您需要使用
StateObject而不是ObservedObject因為您是在視圖內部初始化它,而不是從外部源注入它。
struct MainViewDelegate: View {
@StateObject private var databaseDelegate = DatabaseDelegate()
}
如果你想使用 ObservedObject,你可以在外部創建它并注入到視圖中,如下所示:
var databaseDelegate = DatabaseDelegate()
MainViewDelegate(databaseDelegate: databaseDelegate)
struct MainViewDelegate: View {
@ObservedObject var databaseDelegate: DatabaseDelegate
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/348885.html
上一篇:我正在嘗試在Swift游樂場中呼叫一個函式,但它要求我改為宣告該函式
下一篇:在MVVM中初始化視圖模型
