Swift嵌套查询中的Firebase无法正常工作 [英] Firebase in Swift nested query not working properly

查看:114
本文介绍了Swift嵌套查询中的Firebase无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有如下的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆