在Swift中使用GeoFire查询不会提供有用的输出

时间:2017-03-15 12:41:01

标签: ios swift firebase swift3 geofire

我现在非常绝望,因为我正在尝试在我的Firebase数据库上使用GeoFire来查找附近的用户。 我现在已经被困了两天了。 我搜索了谷歌和stackoverflow很多,并尝试了我在那里找到的一切,但没有任何成功。现在我最后的希望是自己创建这个帖子,并希望有人可以帮助我。

我的数据库看起来像这样:

users
    user_id1
        email: xxx@gmail.com
        username: xxx
    user_id2
        email: yyy@gmail.com
        username: yyy
users_locations
    user_id1
        location
            g: xxxx
            l
                0: 30.0000
                1: 5.0000
    user_id2
        location
            g: yyyy
            l
                0: 30.0010
                1: 5.0010

我不知道是否有必要保存与用户分离的位置数据,但我也试图像这样保存它,结果相同,所以我觉得没关系:

users
    user_id1
        email: xxx@gmail.com
        username: xxx
        location
            g: xxx
            l
                0: 30.0000
                1: 5.0000

现在我正在使用的代码:

要将位置写入数据库,我使用以下命令,该工作正常:

let user = FIRAuth.auth()?.currentUser
let uid = user?.uid

let ref = FIRDatabase.database().reference()
let geofireRef = ref.child("users_locations")
let geoFire = GeoFire(firebaseRef: geofireRef.child(uid!))

geoFire?.setLocation(myLocation, forKey: "location")

现在我尝试使用GeoFire查询向我展示定义半径内的所有用户,这些用户不会为此打印任何内容:

let ref = FIRDatabase.database().reference()
let geofireRef = ref.child("users_location")
let geoFire = GeoFire(firebaseRef: geofireRef)

let circleQuery = geoFire?.query(at: center, withRadius: 10)
circleQuery?.observe(.keyEntered, with: { (key: String?, location: CLLocation?) in
         print("Key '\(key!)' entered the search are and is at location '\(location!)'")
    })

我发现如果我去找我真正的孩子,我会得到一个结果。然后它打印我的实际用户位置和密钥,但这当然不是我想要的。

let geoFire = GeoFire(firebaseRef: geofireRef.child(uid!))

所以我希望GeoFire在'users_locations'中搜索我的uid并返回我定义的半径范围内的所有uid。

对我而言,似乎只是在我的参考(users_location - &gt; user_uid)中定义的子项中搜索名为'location'的子项,如果我尝试查询'users_location',我什么也得不到。< / p>

我做错了什么? 如何让查询搜索引用子项并将其返回给我?

2 个答案:

答案 0 :(得分:4)

使用Geofire时,您有两个数据列表:

  1. 对象列表,在您的情况下为用户
  2. 这些对象的位置列表,通过Geofire维护和查询
  3. 这两个名单确实是分开的。来自Geofire documentation(强调我的):

      

    假设您正在构建一个应用程序来评分条形图并存储条形图的所有信息,例如名称,营业时间和价格范围,/bars/<bar-id>。之后,您希望为用户添加搜索附近酒吧的可能性。这就是GeoFire的用武之地。

         

    您可以使用GeoFire存储每个条形图的位置,使用条形码ID作为GeoFire密钥。然后,GeoFire允许您轻松查询附近的条形码ID(键)。 要显示有关条形图的任何其他信息,您可以在/bars/<bar-id> 加载查询返回的每个条形图的信息。

    我强调了你问题的两个最重要的部分:

    1. 用户列表中的项目及其位置列表应使用相同的密钥(这也是Andrew在答案中指出的内容)。通过使用相同的密钥,您可以轻松地查找用户的位置,反之亦然。
    2. 您需要为查询中的每个密钥单独加载用户。
    3. Andrew展示了如何正确地为每个用户写入位置。剩下的就是加载有关结果范围内每个用户的附加信息。你可以在他.keyEntered处理程序中执行此操作:

      let usersRef = ref.child("users")
      
      let circleQuery = geoFire?.query(at: center, withRadius: 10)
      circleQuery?.observe(.keyEntered, with: { (key: String?, location: CLLocation?) in
      
           print("Key '\(key!)' entered the search are and is at location '\(location!)'")
           // Load the user for the key
           let userRef = usersRef.child(key)
           userRef.observeSingleEvent(FIRDataEventType.value, with: { (snapshot) in
               let userDict = snapshot.value as? [String : AnyObject] ?? [:]
               // ...
           })
      })
      

答案 1 :(得分:2)

尝试使用GeoFire写这些位置。您无需将它们存储在location键下。

let ref = FIRDatabase.database().reference()
let geofireRef = ref.child("users_locations")
let geoFire = GeoFire(firebaseRef: geofireRef)

geoFire?.setLocation(myLocation, forKey: uid!)