【问题标题】:Swift Firebase Realtime Database data not pulled before end of function, data not shown in view [duplicate]Swift Firebase 实时数据库数据未在函数结束前提取,数据未显示在视图中 [重复]
【发布时间】:2026-01-06 06:35:02
【问题描述】:

我对 Swift 还很陌生,所以如果这是显而易见的事情,我深表歉意,但到目前为止我还没有找到答案。

因此,我试图在视图中显示“朋友”列表,并且该数据来自 Firebase 实时数据库。正在拉取数据,但在函数运行完成后才拉取数据。

我也尝试让它与 await async 一起工作,但据我在尝试时看到的,firebase 方法不支持它。

如果您查看下面的函数、视图和打印输出,您就会明白我的意思。

这是我的 firebase 控制器文件中的获取好友功能:

func getFriends(completion: @escaping ([Friend])-> Void) {
        print("start getFriends")
        self.friends = []
        let ref = Database.database().reference(fromURL: "users")
        
        ref.queryOrderedByKey().observeSingleEvent(of: .value) { (snapshot) in
             print("entering data snapshot pull")
            let snapshotValue = snapshot.value as! [String:[String:[String:AnyObject]]]
               
                for (key, _) in snapshotValue {
                    for (_, value) in snapshotValue[key]! {
                        var email = ""
                        var userName = ""
                        var id = ""
                        for (key, value) in value {
                            switch key{
                                case "email":
                                    email = value as? String ?? ""
                                case "userName":
                                    userName = value as? String ?? ""
                                case "id":
                                    id = value as? String ?? ""
                                default:
                                    print("")
                            }
                    }
                        print("--------------------------")
                        print(userName)
                        print(email)
                        print(id)
                        self.friends.append(Friend(userName: userName, email: email, id: id))
                }
            }
             print("leaving data snapshot pull")
             
        }
        print("end getFriends")
        completion(friends)
      }

这是我的看法:

struct ChatListView: View {
    typealias Friend = ChatList<String>.Friend
    @State var friends : [Friend] = []
    @ObservedObject var chatListUI: ChatListUI
    var firebaseController = FirebaseDatabaseController()
    var body: some View {
        Button(action: {
            do {
                try Auth.auth().signOut()
            }
            catch {
                print("cant log out")
            }
        }, label: {
            Text("Log out")
        })
        List {
            ForEach(friends) { Friend in
                Text(Friend.userName)
            }
        }.onAppear(perform: {
            print("start onAppear in view")
            firebaseController.getFriends(){ productsArray in
                self.friends = productsArray
            }
            print("friends count:")
            print(friends.count)
            print("end onAppear  in view")
        })
    }
}

这是输出:

2022-01-05 13:20:32.273898+0100 ChatBuddy[2094:38382] [error] warning:  View context accessed for persistent container ChatBuddy with no stores loaded
CoreData: warning:  View context accessed for persistent container ChatBuddy with no stores loaded
start onAppear in view
start getFriends
end getFriends
friends count:
0
end onAppear  in view
2022-01-05 13:20:32.655201+0100 ChatBuddy[2094:38562] 8.10.0 - [GoogleUtilities/AppDelegateSwizzler][I-SWZ001014] App Delegate does not conform to UIApplicationDelegate protocol.
entering data snapshot pull
--------------------------
ArdianNuhiji
Nuhijiardian@hotmail.com
ItAoaKj5ZTamf3BHikbdYsHmMhq2
--------------------------
Test
Test@hotmail.com
QkpSyxmV5MfqmhPobdOtQI97cdP2
--------------------------
Test2
Test2@hotmail.com
8xSa6Ff73JMJSq1418rgWtil6442
--------------------------
Test1
Test1@hotmail.com
WQ3f9OnmJTOtbxdEXMEB2j4q3bu2
leaving data snapshot pull
2022-01-05 13:20:32.917846+0100 ChatBuddy[2094:38562] [boringssl] boringssl_metrics_log_metric_block_invoke(151) Failed to log metrics

【问题讨论】:

    标签: ios swift firebase firebase-realtime-database swiftui


    【解决方案1】:

    问题在于您的 getFriends 方法。在您的代码中 observeSingleEvent 是一个异步函数,因此仅在该闭包内调用 completion(friends) 即可解决问题。改变方法如下。

    func getFriends(completion: @escaping ([Friend])-> Void) {
        print("start getFriends")
        self.friends = []
        let ref = Database.database().reference(fromURL: "users")
        
        ref.queryOrderedByKey().observeSingleEvent(of: .value) { (snapshot) in
            print("entering data snapshot pull")
            let snapshotValue = snapshot.value as! [String:[String:[String:AnyObject]]]
            
            for (key, _) in snapshotValue {
                for (_, value) in snapshotValue[key]! {
                    var email = ""
                    var userName = ""
                    var id = ""
                    for (key, value) in value {
                        switch key{
                        case "email":
                            email = value as? String ?? ""
                        case "userName":
                            userName = value as? String ?? ""
                        case "id":
                            id = value as? String ?? ""
                        default:
                            print("")
                        }
                    }
                    print("--------------------------")
                    print(userName)
                    print(email)
                    print(id)
                    self.friends.append(Friend(userName: userName, email: email, id: id))
                }
            }
            print("leaving data snapshot pull")
            // CHANGE -----
            completion(friends)
        }
        print("end getFriends")
        
    }
    

    【讨论】:

    • 非常感谢!这为我解决了问题!
    • 不客气。