Swift Firebase 实时数据库数据未在函数结束前提取,数据未显示在视图中
Swift Firebase Realtime Database data not pulled before end of function, data not shown in view
我是 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
问题出在您的 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")
}
我是 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
问题出在您的 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")
}