Swift嵌套查询中的Firebase无法正常工作 [英] Firebase in Swift nested query not working properly
问题描述
我有如下的JSON结构:
{
groups:{
-KAv867tzVgIghmr15CM:{
author:ruben,
name:Item A
},
-KAv87nqLEG1Jtc04Ebn:{
author:ruben,
name:Item B
},
-KAv88yZe8KTfkjAE7In:{
author:ruben,
name:Item C
}
},
users:{
rsenov:{
avatar:guest,
email:ruben@ruben.com,
groups:{
-KAv867tzVgIghmr15CM:true,
-KAv87nqLEG1Jtc04Ebn:true ,
-KAv88yZe8KTfkjAE7In:true
}
}
}
}
每个用户都有一个带有childByAutoId()键的元素groups,然后列出应用程序中存在的所有组。
每当我运行应用程序,我得到当前用户登录的网址引用,和我得到该用户的组列表(在这种情况下,登录用户是rsenov,有3个组)。
对于这个用户所属的每个组,我遍历组url参考,寻找获得这3个组的信息。
我这样做这个:
func loadTable(){
self.groups = []
var counter = 0
self.meses = []
var tempItems = [String]()
DataService.dataService.CURRENT_USER_GROUPS_REF.observeEventType(.Value,withBlock:{snapshot in
if snapshots = snapshot.children.allObjects as?[FDataSnapshot] {
tempItems = []
快照中的快照{
DataService.dataService.GROUPS_REF.childByAppendingPath (snap.key).queryOrderedByChild(name)。observeEventType(.Value,withBlock:{snapshot in $ b $ if postDictionary = snapshot.value as?Dictionary< String,AnyObject> {
tempItems.append (snapshot.value.objectForKey(name)as!String)
let key = snapshot.key
let group = Group(key:key,dictionary:postDictionary)
self.groups.insert(group,atIndex:0)
}
counter ++
if(counter == snapshots.count){
self.meses = tempItems
self.miTabla.reloadData()
})
}
}
})
}
<我认为这样做并不是一个很好的主意。例如,如果GROUPS_REF url中的某个子节点发生更改,则代码只运行在该嵌套代码中,并且由于它没有从for循环获取的snap.key值,所以它不起作用。
在这种情况下,做好查询的最好方法是什么? 唷,那花了一些时间写的。主要是因为我没有很多的iOS / Swift:
$ p $ let ref = Firebase(url:https:// stackoverflow。 firebaseio.com/35514497)
让CURRENT_USER_GROUPS_REF = ref.childByAppendingPath(users / rsenov / groups)
let GROUPS_REF = ref.childByAppendingPath(groups)
var counter:UInt = 0
var groupNames = [String]()
CURRENT_USER_GROUPS_REF.observeEventType(.Value,withBlock:{groupKeys in $ b $ groupKeys.children中的groupKey {
print(Loading group \(groupKey.key))
GROUPS_REF.childByAppendingPath(groupKey.key).observeSingleEventOfType(.Value,withBlock:{snapshot in
print(snapshot.value)
if(snapshot.childSnapshotForPath(name)。exists()){
groupNames.append(snapshot.value.objectForKey(name)as!String)
}
counter ++
if(counter == groupKeys.childrenCount){
print(groupNames)
}
})
}
})
,这是如何创建一个最小,完整的可验证示例。该代码没有外部依赖(例如代码中的 Group
和 DataService
),只包含与答案相关的内容。
$ b 重要的部分:
observeSingleEventOfType
来获取每个组,因为我不想在组更改时获得更多的回调函数。
snapshot.childSnapshotForPath name)。exists()
来检查你的组是否有名字。您可能希望确保它们都具有名称,或者将其添加到列表中,并使用真实应用程序中的其他属性。
I have a JSON structure like the following:
{
"groups" : {
"-KAv867tzVgIghmr15CM" : {
"author" : "ruben",
"name" : "Item A"
},
"-KAv87nqLEG1Jtc04Ebn" : {
"author" : "ruben",
"name" : "Item B"
},
"-KAv88yZe8KTfkjAE7In" : {
"author" : "ruben",
"name" : "Item C"
}
},
"users" : {
"rsenov : {
"avatar" : "guest",
"email" : "ruben@ruben.com",
"groups" : {
"-KAv867tzVgIghmr15CM" : "true",
"-KAv87nqLEG1Jtc04Ebn" : "true",
"-KAv88yZe8KTfkjAE7In" : "true"
}
}
}
}
Every user has the element "groups" with a childByAutoId() key. Then I have the list of all the groups that exists in the app.
Every time that I run the app, I get the current user logged url reference, and I get the list of the groups of that user (in this case, the logged in user is "rsenov" that has 3 groups). For every group that this user belongs to, I iterate through the groups url reference, looking for getting the information of that 3 groups.
I do this like this:
func loadTable() {
self.groups = []
var counter = 0
self.meses = []
var tempItems = [String]()
DataService.dataService.CURRENT_USER_GROUPS_REF.observeEventType(.Value, withBlock: { snapshot in
if let snapshots = snapshot.children.allObjects as? [FDataSnapshot] {
tempItems = []
for snap in snapshots {
DataService.dataService.GROUPS_REF.childByAppendingPath(snap.key).queryOrderedByChild("name").observeEventType(.Value, withBlock: { snapshot in
if let postDictionary = snapshot.value as? Dictionary<String, AnyObject> {
tempItems.append(snapshot.value.objectForKey("name") as! String)
let key = snapshot.key
let group = Group(key: key, dictionary: postDictionary)
self.groups.insert(group, atIndex: 0)
}
counter++
if (counter == snapshots.count) {
self.meses = tempItems
self.miTabla.reloadData()
}
})
}
}
})
}
I think this is not a good idea of iterating in that way. For example, if there is a change of some child in the GROUPS_REF url, the code only runs in that nested code, and since it doesn't have the "snap.key" value got from the for loop, it doesn't work.
Which is the best way to do a good query in this case?
Phew, that took some time to write. Mostly because I don't iOS/Swift a lot:
let ref = Firebase(url: "https://stackoverflow.firebaseio.com/35514497")
let CURRENT_USER_GROUPS_REF = ref.childByAppendingPath("users/rsenov/groups")
let GROUPS_REF = ref.childByAppendingPath("groups")
var counter: UInt = 0
var groupNames = [String]()
CURRENT_USER_GROUPS_REF.observeEventType(.Value, withBlock: { groupKeys in
for groupKey in groupKeys.children {
print("Loading group \(groupKey.key)")
GROUPS_REF.childByAppendingPath(groupKey.key).observeSingleEventOfType(.Value, withBlock: { snapshot in
print(snapshot.value)
if (snapshot.childSnapshotForPath("name").exists()) {
groupNames.append(snapshot.value.objectForKey("name") as! String)
}
counter++
if (counter == groupKeys.childrenCount) {
print(groupNames)
}
})
}
})
By the way, this is how you create a minimal, complete verifiable example. The code has no external dependencies (such as Group
and DataService
in your code) and only contains what's relevant to the answer.
The important bits:
- I used
observeSingleEventOfType
to get each group, since I don't want to get more callbacks if a group changes - I use
snapshot.childSnapshotForPath("name").exists()
to check if your group has a name. You probably want to either ensure they all have names or add them to the list with some other property in the real app.
这篇关于Swift嵌套查询中的Firebase无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!