这个问题可能是因为我对补全以及如何正确使用它们一无所知,但我一直在研究,只是找不到解决我的问题的方法。
我有一个从数据库中获取用户数据的函数,然后我想将从数据库中获取的值分配给我的表视图单元格。如果我的 AssignValueToUserObject 方法中没有完成,则在我实际获取导致错误的值之前调用我的表格视图单元格。
所以我发现完成是要走的路,到目前为止它对我有用,但是现在我使用的是表格视图单元格,我实际上无法在完成中手动调用表格视图方法,所以我不不知道如何使用该方法获取数据,然后将值分配给表格视图单元格。
这是我的方法:
extension MoneyGroupViewController {
public func AssignValueToUserObject(completion: @escaping () -> Void) {
// Get user unique id
guard let uid = Auth.auth().currentUser?.uid else {
print("Could not get user id")
return
}
Database.database().reference().child("users").child(uid).observeSingleEvent(of: .value, with: { [self] snapshot in
if let dictionary = snapshot.value as? [String: AnyObject] {
user.first_name = dictionary["first_name"] as! String
user.last_name = dictionary["last_name"] as! String
user.email = dictionary["email"] as! String
user.profile_picture = dictionary["profile_picture"] as? String
completion() //call once the action is done
}
}, withCancel: nil)
} // End AssignValueToUserObject Method
} // End extension
这是我的表格视图单元格函数,它是我的视图控制器:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = groupTableView.dequeueReusableCell(withIdentifier: "MoneyGroupTableViewCell", for: indexPath) as! MoneyGroupTableViewCell
cell.userName.text = userArray[indexPath.row].first_name + " " + userArray[indexPath.row].last_name
if (user.profile_picture != "") {
let url = URL(string: user.profile_picture!)!
URLSession.shared.dataTask(with: url, completionHandler: { data, _, error in
DispatchQueue.main.async {
cell.userImage.layer.cornerRadius = max(cell.userImage.frame.width, cell.userImage.frame.height)/2
cell.userImage.layer.borderWidth = 1
cell.userImage.image = UIImage(data: data!)
}
}).resume() // End URLSession
}
return cell
}
最后,这是我调用方法的方式:
override func viewDidLoad() {
super.viewDidLoad()
AssignValueToUserObject {
// I should call the table view function here but I don't know how
}
}
更新
是的,我的单元格应该显示用户的信息(名字、姓氏、电子邮件和可选的个人资料图片)。
我可能想在我的 userArray 中添加“组”中的所有用户,但现在我没有实现该功能,我只是在 userArray 中使用相同的用户来测试我的表视图。
所以 userArray 现在应该只有相同的用户,但我的问题仍然存在,我不知道如何在表格视图单元格调用之前从数据库中获取用户的信息。 >
答案 0 :(得分:1)
你想错了。
您不应该尝试将内容分配给您的表格视图单元格。您应该将新获取的数据保存到您的模型中,然后告诉您的表视图它需要更新。如果您为现有单元格加载了新内容,请使用 reloadRows(at:with:)
告诉表格视图为该数据重新加载单元格。然后表格视图将询问更新单元格的数据源。数据源将根据您更新的数据构建更新后的单元格,并正确显示。
请注意,如果您从完成处理程序内部调用 reloadRows(at:with:)
,您应该将调用包装在对 DispatchQueue.main.async()
的调用中,以便它在主线程上执行。
看看你的代码,你有很多问题。
你的表格视图应该显示什么?包含用户信息的单元格? (名字和姓氏、电子邮件地址和个人资料照片?
你的 userArray 包含什么?什么类型的结构数组?用户信息?编辑您的问题以包含该信息。
看起来您实际上需要完成 2 个单独的异步操作才能显示有关用户的所有信息:您需要执行数据库提取以获取有关用户的信息(包括指向其个人资料图片的 URL,然后您需要拨打网络电话(至 URLSession.shared.dataTask
以下载您的图片。
您的 AssignValueToUserObject
函数似乎总是读取单个用户的信息,但您配置表格视图单元格的代码似乎从数组 userArray
中获取数据,**EXCEPT 用于 ** 图像 URL在 user.profile_picture
中,这将始终用于您在 AssignValueToUserObject
中引用的单个用户。
简而言之,您的代码非常混乱,如果没有清楚地描述您要执行的操作,我们无法帮助您理顺它。
答案 1 :(得分:1)
您不需要在这里使用完成块。
只要您需要 tableview 重新加载其内容,只需使用 UITableView 的实例方法 reloadData()
。
这可能是当您的数据模型发生变化时。
调用 tableView.reloadData()
将运行所有数据源方法,包括:
cellForItemAt:
和 numberOfRows:
在这种情况下,我假设你应该有这样的用户结构/类:
struct UserData
{
var first_name : String = ""
var last_name : String = ""
var email : String = ""
var profile_picture : String = ""
}
尝试这样做:
class YourClass : UIViewController {
//Create an Empty User (As you want to implement with single user first)
let user : UserData = UserData()
override func viewDidLoad() {
super.viewDidLoad()
AssignValueToUserObject()
}
方法:
extension MoneyGroupViewController {
public func AssignValueToUserObject() {
// Get user unique id
guard let uid = Auth.auth().currentUser?.uid else {
print("Could not get user id")
return
}
Database.database().reference().child("users").child(uid).observeSingleEvent(of: .value, with: { [weak self] snapshot in
if let dictionary = snapshot.value as? [String: AnyObject] {
user.first_name = dictionary["first_name"] as! String
user.last_name = dictionary["last_name"] as! String
user.email = dictionary["email"] as! String
user.profile_picture = dictionary["profile_picture"] as? String
}
//Reload Your Tableview once you're done Fetching Data from Firestore
DispatchQueue.main.async {
self?.YOURTABLEVIEW.reloadData()
}
}, withCancel: nil)
} // End AssignValueToUserObject Method
}
Tableview 的 cellForRowAt:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = groupTableView.dequeueReusableCell(withIdentifier: "MoneyGroupTableViewCell", for: indexPath) as! MoneyGroupTableViewCell
cell.userName.text = user.first_name + " " + user.last_name
//Note: You should use "SDWebImage" or "Kingfisher" Library for async image downloading
if let url = URL(string: user.profile_picture)
{
URLSession.shared.dataTask(with: url, completionHandler: { data, _, error in
DispatchQueue.main.async {
cell.userImage.layer.cornerRadius = max(cell.userImage.frame.width, cell.userImage.frame.height)/2
cell.userImage.layer.borderWidth = 1
cell.userImage.image = UIImage(data: data!)
}
}).resume() // End URLSession
}
return cell
}
注意:
AssignValueToUserObject()
将用一些数据填充用户对象。reloadData()
将调用,它将重新加载 Tableview 并使用新数据填充单元格中的数据。