我正在我的应用上创建一个朋友列表,fetchfriends创建一个用户列表,该用户是该用户,然后查看此列表并使用好友信息填充表格视图。这似乎可以正常工作,但出于某种原因fetch用户正在运行之前获取朋友可以有人帮我这个吗?这是我的代码。我甚至尝试了一个条件语句,现在已被注释掉了,它从未以这种方式运行第二个函数。
override func viewDidLoad() {
super.viewDidLoad()
ref = FIRDatabase.database().reference()
friendsTableView.delegate = self
friendsTableView.dataSource = self
fetchfriends()
//if userspresent == true {
fetchuser()
// }
// Do any additional setup after loading the view.
}
func fetchfriends () {
ref.child("users").child(userID!).child("friends").observeSingleEvent(of: .value, with: { (snapshot) in
if let value = snapshot.value as? NSDictionary {
let userName = value["username"] as? String ?? ""
let friendid = value["userid"] as? String ?? ""
self.userIds.append(friendid)
self.userspresent = true
print(userName, friendid)
}
})
}
// var index1:Int = 0
//if userspresent == true {
func fetchuser () {
//let count = userIds.count
for index1 in 0...userIds.count-1 {
ref.child("users").child(userIds[index1]).observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let user = User()
let userName = value?["username"] as? String ?? ""
let email = value?["email"] as? String ?? ""
let profileImageUrl = value?["profileImage"] as? String ?? ""
user.userName = userName
user.email = email
user.profileImageUrl = profileImageUrl
print(user)
self.users.append(user)
DispatchQueue.main.async {
self.friendsTableView.reloadData()
}
print(user.userName!, user.email!)
// print(snapshot)
}, withCancel: nil)
}
}
答案 0 :(得分:3)
@Taylor M是对的。这些是异步网络操作,因此您无法确定首先完成哪一个。但是,由于fetchuser
依赖于fetchfriends
中生成的数据(即userIds
中会有值),您只需将一个闭包作为参数添加到fetchfriends
:< / p>
func fetchfriends (_ completion: ((Void) -> Void)?) {
ref.child("users").child(userID!).child("friends").observeSingleEvent(of: .value, with: { (snapshot) in
if let value = snapshot.value as? NSDictionary {
let userName = value["username"] as? String ?? ""
let friendid = value["userid"] as? String ?? ""
self.userIds.append(friendid)
self.userspresent = true
print(userName, friendid)
// call the closure function upon completion
completion?()
}
})
现在,当您在fetchfriends
中致电viewDidLoad
时,只需执行以下操作:
fetchfriends {
// this will be called when the friends are successfully fetched
self.fetchuser()
}
答案 1 :(得分:0)
正在发生的是异步网络呼叫。如果您的代码如下所示,在获取朋友之前说fetch用户正在运行是不正确的:
csvp.writeln()
在override func viewDidLoad() {
...
fetchfriends()
//if userspresent == true {
fetchuser()
// }
}
调用中,您为此函数提供了一个闭包,以便在 firebase观察到该事件后运行。
所以你拨打observeSingleEvent
(第一个)来调用fetchfriends
。操作系统将此网络调用放在后台线程上以执行其工作,并在网络调用完成时,执行提供的闭包。同时,在主线程上,您的程序继续运行并调用observeSingleEvent
(秒),它还调用fetchuser
并将该调用和闭包放在不同的后台线程上,并且程序继续运行。很可能看起来好像首先运行用observeSingeEvent
方法编写的闭包,因为该网络花费较少的时间并且是第一个回来的。