首页 > 解决方案 > Firebase生成的数据表无法稳定显示

问题描述

我需要开发一个具有排行榜功能的移动应用程序。排行榜只显示在一个选项卡上,但是每次我从另一个选项卡返回此页面时,排行榜总是会立即消失(请查看此屏幕记录)。有没有办法让数据稳定显示?

这是我的代码片段:

// LeaderboardView.swift

import SwiftUI

struct Leaderboard: View {
    @ObservedObject private var users = UserViewModel()
    var body: some View {
// ...
            NavigationView {
                List(users.topFiveUsers) {
                    user in
                    VStack {
                        HStack {
                            Text(verbatim: user.name).font(.headline)
                            Text(verbatim: String(user.xp)).font(.subheadline)
                        }
                    }
                }
            }
            .navigationTitle(Text("Leaderboard"))
            Spacer()
        }
        .background(Color.white)
    }
}

struct Leaderboard_Previews: PreviewProvider {
    static var previews: some View {
        Leaderboard()
    }
}
// UserViewModel.swift

import Foundation
import Firebase
import FirebaseFirestore

class UserViewModel: ObservableObject {
    @Published var topFiveUsers = [User]()
    private var db = Firestore.firestore().collection("Users")
        
    public init() {
        let top5 = db.order(by: "xp", descending: true).limit(to: 5)
        top5.addSnapshotListener { (QuerySnapshot, error) in
            guard let documents = QuerySnapshot?.documents else {
                print("Document is empty")
                return
            }
            self.topFiveUsers = documents.map {
                (QueryDocumentSnapshot) -> User in
                let data = QueryDocumentSnapshot.data()
                let xp = data["xp"]
                let name = data["username"]
                return User(name:name as? String ?? "", xp:xp as? Int ?? 0)
            }
        }
    }
}
// User.swift

import SwiftUI
import Firebase

class User : ObservableObject, Identifiable {
    @Published var name = ""
    @Published var bio = ""
    @Published var interest = ""
    @Published var level = 1
    @Published var xp = 0
    @Published var email = ""
    @Published var image_Data = Data(count: 0)
    @Published var picker = false
    
    let ref = Firestore.firestore()
    
    @Published var isLoading = false
    @AppStorage("status") var status = false
    
    // common init
    init() {
        
    }
    
    //initializer for leaderboard collection
    init(name: String, xp: Int) {
        self.name = name
        self.xp = xp
        self.level = User.xp2Level(xp: xp)
    }
}
// ContentView.swift

struct ContentView: View {
    init() {
        UITabBar.appearance().isHidden = true
    }
    @State var centerX : CGFloat = 0
    @State var goToHome = false
    @State var edge = UIApplication.shared.windows.first?.safeAreaInsets
//    @Environement(.verticalSizeClass) var size
    var body: some View {
        
        ZStack {
            if goToHome {
                
                NavigationView {
                    CustomTabView(centerX: $centerX)
                        .navigationBarTitleDisplayMode(.inline)
                        .navigationBarHidden(true)
                }
            }
            else {
                OnBoardScreen()
            }
        }
        .onReceive(NotificationCenter.default.publisher(for:Notification.Name("Success")), perform: {
            _ in withAnimation{self.goToHome = true}
        })
    }
        
}

struct CustomTabView : View {
    //swich tabs
    @State var selectedTab = "home"
    @Binding var centerX : CGFloat
    var body : some View {
        
        ZStack(alignment: Alignment(horizontal: .center, vertical: .bottom)){
            TabView(selection: $selectedTab) {
                Home()
                    .tag("home")
                Leaderboard()
                    .tag("Leaderboard")
                Pal()
                    .tag("profile")
            }
//            .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
            .ignoresSafeArea(.all, edges: .all)
            
//            Spacer()
            HStack(spacing: 0) {
                ForEach(tabs, id: \.self) {image in
                    GeometryReader {reader in
                        TabButton(image: image, centerX: $centerX, rect:reader.frame(in:.global), selectedTab: $selectedTab)
                        //setting initial curve
                            .onAppear(perform: {
                                if image == tabs.first{
                                    centerX = reader.frame(in: .global).midX
                                }
                            })
                    }
                    .frame(width: 50, height: 30)
                    if image != tabs.last {Spacer(minLength: 0)}
                }
            }
            .padding(.horizontal, 30)
//            .padding(.top)
            .padding(.vertical, 17)
            .padding(.bottom, 20)
            .padding(.bottom, UIApplication.shared.windows.first?.safeAreaInsets.bottom == 0 ? 15: 0)
            .background(Color("5324FF").clipShape(AnimatedShape(centerX: centerX)))
            .shadow(color: Color.blue.opacity(0.1), radius: 5, x: 0, y: -5)
//            .ignoresSafeArea(.all, edges: .all)
        }
        .ignoresSafeArea(.all, edges: .all)
           
    }
}

标签: iosswiftfirebaseswiftuifrontend

解决方案


即使@State 有效,您也应该使用@StateObject。如果使用@State,SwiftUI 可能会随机销毁 Object。

@StateObject private var users = UserViewModel()

推荐阅读