我是Swift 3和Firebase的新手,因此在从两个不同节点检索数据并将其显示在一个表格视图单元格中存在一些问题。我在Stack Overflow上找到了一些类似的问题,如下所示:
Firebase - iOS Swift: load table view cell with data retrieved from two separate child nodes
但无法将其应用于我的代码,因为这些示例对于提问者来说过于具体,或者我对Firebase缺乏了解,导致我无法继续提供所提供的答案。
我的应用程序是使用Xcode-8在Swift 3中编写的,并使用Firebase进行数据持久化。该应用程序的目的是允许用户提交不同的锻炼计划以供其他用户使用。用户提交的程序将作者的uid与它们相关联,我计划使用它来根据此uid值从单独的节点检索用户的用户名。
我的Firebase设置:
"programs" : {
"-KYF3o3YD6F3FEXutuYH" : {
"content" : "Program Content Goes Here...",
"duration" : "4 Weeks",
"title" : "Chest Blast",
"type" : "Hypertrophy",
"uid" : "oLy9GOzDyKht7WWVZgpd3jPHxsE3"
},
"-KYF4ev88FQ2nEr6yTOW" : {
"content" : "Program Content Goes Here...",
"duration" : "6 Weeks",
"title" : "Full Back Workout",
"type" : "Strength",
"uid" : "oLy9GOzDyKht7WWVZgpd3jPHxsE3"
},
"-KZRYF9A8-8OHCNzOoPT" : {
"content" : "Eugene and Eamon",
"duration" : "4 Weeks",
"title" : "abc",
"type" : "abc",
"uid" : "oLy9GOzDyKht7WWVZgpd3jPHxsE3"
},
"-KbKNdrAcBarpaNoGf_e" : {
"content" : "Test",
"duration" : "test",
"title" : "New Test",
"type" : "test",
"uid" : "oLy9GOzDyKht7WWVZgpd3jPHxsE3"
},
"-KbKnXnyzj_EJp_wNw5y" : {
"content" : "1. Barbell Bench Press\n\nWhy it's on the list: You can generate the most power with barbell lifts, so the standard barbell bench allows you to move the most weight. It's also an easier lift to control than pressing with heavy dumbbells. The exercise is easy to spot and relatively easy to learn (if not master), There are plenty of bench-press programs you can follow to increase your strength.\n\n1. Barbell Bench Press\n\nWhy it's on the list: You can generate the most power with barbell lifts, so the standard barbell bench allows you to move the most weight. It's also an easier lift to control than pressing with heavy dumbbells. The exercise is easy to spot and relatively easy to learn (if not master), There are plenty of bench-press programs you can follow to increase your strength.",
"duration" : "1",
"title" : "1",
"type" : "1",
"uid" : "oLy9GOzDyKht7WWVZgpd3jPHxsE3"
}
},
"users" : {
"hds1WketiAUELVDOz1Dprvlu0KE3" : {
"username" : "Example"
},
"oLy9GOzDyKht7WWVZgpd3jPHxsE3" : {
"username" : "Test"
}
}
应用程序中的表格如下所示:
正如你所看到的,目前作者只是被他们的uid所指示。这很容易,因为我将它存储在与显示的所有其他数据相同的位置但我需要使用该uid值来搜索另一个节点并获取与其关联的用户名并将其显示在现在显示uid的位置。
以下是我用来检索和显示数据的代码。我的主要问题是:
1:我可以使用什么查询在用户节点中搜索匹配的uid,只获取该人的用户名并将其显示在表格视图中?
2:我应该在代码中放置该查询?我想把它放在func tableView()方法中,因为我可以在每次将新帖子添加到单元格时搜索用户,这样我就不必再创建另一个NSMutable数组来保存用户谁可能甚至没有帖子。非常感谢您提供任何帮助。
@IBOutlet weak var programsTableView: UITableView!
var programs = NSMutableArray()
override func viewDidLoad() {
super.viewDidLoad()
self.programsTableView.delegate = self
self.programsTableView.dataSource = self
//Call load data method to populate table with data from Firebase
loadData()
}
//Method to load data from Firebase
func loadData(){
FIRDatabase.database().reference().child("programs").observeSingleEvent(of: .value, with: { (snapshot) in
//Snapshot holds value and it is casted to NS Dictionary
if let programsDictionary = snapshot.value as? [String: AnyObject]{
for program in programsDictionary{
self.programs.add(program.value)
}
self.programsTableView.reloadData()
}
})
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! AllProgramsTableViewCell
// Configure the cell...
let program = self.programs[indexPath.row] as! [String: AnyObject]
//Populate row
//Grab title and add it to cell
cell.titleLabel.text = program["title"] as? String
//Grab type and add it to cell
cell.typeLabel.text = program["type"] as? String
//Grab duration and add it to cell
cell.durationLabel.text = program["duration"] as? String
//Grab content and add it to cell
cell.contentTextView.text = program["content"] as? String
//Grab author and add it to cell
cell.authorLabel.text = program["uid"] as? String
return cell
}
答案 0 :(得分:2)
帮助你的一些事情。
1:我可以使用什么查询来搜索用户节点以查找匹配的uid 并抓住该人的用户名并将其显示在表格中 查看?
首先,更改您的用户节点并利用uid作为每个用户的密钥
users
uid_0
name: "Hans"
userName: "pump_u_up"
uid_1
name: "Franz"
userName: "abs_of_steel"
这可以避免查询。查询更重'比观察并获取更多资源。通过使用uid,您可以直接捕获用户信息。例如:
let userRef = rootRef.child("uid from programs node")
userRef.observeSingleEvent(of: .value, with: { snapshot in
let userDict = snapshot.value as! [String:AnyObject]
let userName = userDict["userName"] as! String
print(userName)
})
2:我应该在代码中放置该查询?我只想 把它放在func tableView()方法中,因为我可以搜索 用户每次将新帖子添加到单元格时都是这样的 不必制作另一个NSMutable数组来容纳可能的用户 甚至没有帖子。非常感谢您提供任何帮助。
既然你已经拥有了捕获用户信息的代码,那么添加它就很容易,但是,我建议采用与发布的方法略有不同的方法。
从ProgramClass开始
class ProgramClass {
var key = ""
var content = ""
var duration = ""
var username = ""
}
并填充数据源:
ref.child("programs").observeSingleEvent(of: .value, with: { (snapshot) in
for snap in snapshot.children {
let programSnap = snap as! FIRDataSnapshot
let programKey = programSnap.key //the key of each program
let programDict = programSnap.value as! [String:AnyObject] //program child data
var aProgram = ProgramClass()
aProgram.key = programKey
aProgram.content = programDict["content"] as! String
//etc
let uid = programDict["uid"] as! String
let userRef = ref.child("users").child(uid)
userRef.observeSingleEvent(of: .value, with: { snapshot in
let userDict = snapshot.value as! [String:AnyObject]
let userName = userDict["userName"] as! String
aProgram.username = userName
self.programsArray.append[aProgram]
})
}
}
上面的代码可以大大缩短,但是为了便于阅读,它会更加冗长。
哦,不要忘记以Swifty方式定义数据源数组:
var programsArray = [ProgramClass]()
答案 1 :(得分:-1)
更新: getUserName
无法正常工作,因为observeSingleEvent
是一个asyc调用。 (感谢@Aodh)
PS:我不知道是否最好删除答案或将其作为一个不好的例子?
解决方案只是再次检索用户数据:
您应该更改您未在程序中保存uid的架构,而不是userId
"programs":
"programId1234":
[...]
"userId": "userid12345
"users":
"userId1234":
"uid": "uidxxxxxx"
"username" : "jim"
代码:
FIRDatabase.database().reference().child("programs").observeSingleEvent(of: .value, with: { (snapshot) in
//Snapshot holds value and it is casted to NS Dictionary
//change to var!
if var programsDictionary = snapshot.value as? [String: AnyObject]{
for program in programsDictionary{
// add there
let programDictionary = program.value as? [String: AnyObject]
let authorUid = programDictionary["userId"] as? String
let authorName = getUserName(forUid: authorUid)
programDictionary["authorname"] = autorName
//
self.programs.add(programDictionary)
}
self.programsTableView.reloadData()
}
})
func getUserName(forUid userID: String) -> String {
var userName = nil
FIRDatabase.database().reference().child("users").child(userID)
.observeSingleEvent(of: .value, with: { (snapshot) in
if let userDictionary = snapshot.value as? [String: AnyObject]{
userName = userDictionary["username"] as? String
}
})
return userName
}
以后再也不需要转换它了 - 你可以改变这一行:
// Configure the cell...
let program = self.programs[indexPath.row] as! [String: AnyObject]
到
// Configure the cell...
let program = self.programs[indexPath.row]
以下是 join
来电的示例:https://firebase.googleblog.com/2013/10/queries-part-1-common-sql-queries.html#join