一尘不染

按距离Firebase用户位置附近的距离对数组进行排序

swift

无法弄清楚如何对用户附近的 地址 进行自动 排序 。我不明白从哪里开始以及如何编写代码。

我的 firebase中 有地址。地址的类型为字符串(不是纬度/经度)。例:

"Москва, Электрозаводская, 21"
"Москва, Арбат, Староконюшенный переулок, дом 43"
"Москва, улица 1-я Бухвостова, дом 12/11, корпус 53"

我知道需要从firebase 使用 查询 ,但是如何使用 query ,我现在不明白。

这是我的代码:

class PhotoStudiosViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIScrollViewDelegate {

    @IBOutlet weak var tableView: UITableView!

    var theStudios: [Studio] = []

    var studiosRef: DatabaseReference!

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(true)

        tableView.estimatedRowHeight = 475
        tableView.rowHeight = UITableViewAutomaticDimension

        loadDataFromFirebase()

    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return theStudios.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! PhotoStudiosTableViewCell

        cell.addressLabel.text = theStudios[indexPath.row].studioAddress

        return cell
    }

    func loadDataFromFirebase() {

        studiosRef = Database.database().reference(withPath: "Addresses")

        let time = DispatchTime.now() + 0.5

        studiosRef.observe(.value, with: { (snapshot) in

        DispatchQueue.main.asyncAfter(deadline: time) {

            for imageSnap in snapshot.children {

                let studioObj = Studio(snapshot: imageSnap as! DataSnapshot)

                self.theStudios.append(studioObj)

            }

            self.tableView.reloadData()

        }

    })

}



class Studio {

    var ref: DatabaseReference! 
    var studioAddress: String = ""

    init(snapshot: DataSnapshot) {

        ref = snapshot.ref
        studioName = snapshot.key

        let value = snapshot.value as! NSDictionary

        studioAddress = value["address"] as? String ?? "---"

    }
}

如何使用 Firebase中的* 数据在用户附近自动 排序 地址? *


阅读 198

收藏
2020-07-07

共1个答案

一尘不染

这是一个复杂的过程,需要多个步骤。我将尝试解释这些步骤,但是您必须做一些工作才能将其转变为可运行的解决方案。

地理编码

首先:您所拥有的地址字符串不是位置。计算机无法比较两个这样的字符串并可靠地知道它们之间的距离。

因此,您要做的第一件事就是将地址转换为更可靠的位置指示,即转换为纬度和经度(也就是经/纬度)。将地址转换为经/纬度的过程称为地址解析。这确实不是一门精确的科学,但是有很多服务都可以很好地利用此地理编码位。

在此地址解析过程结束时,您将为每个地址输入经纬度组合。这使问题重新回到数学上,这是一门更为精确的科学。

地理查询

接下来,您需要比较每个地址的经纬度,并计算它们之间的距离。如果您愿意忽略两极附近的错误以及诸如此类的事情,这 一门相对精确的科学。

不幸的是,Firebase实时数据库本身只能对单个属性进行排序/过滤。由于位置由两个属性(纬度和经度)组成,因此如果没有魔法,就无法过滤位置。

幸运的是,有人想出了一种将经/纬度信息转换为单个字符串的方法,称为geohash。例如:旧金山Google办公室位于lat
/ lon 37.7900515,-122.3923805,即译为geohash 9q8yyz。Mountain
View中的Googleplex位于lat / lon 37.4219999,-122.0862515,即译为geohash 9q9hvu

与您最初使用的地址不同,geohash具有很好的可比性。引用(链接的)维基百科解释:

附近的位置[具有]类似的前缀。共享前缀越长,两个位置越近。

在上面的两个示例中,您可以看到两个位置相对靠近,因为它们都以 9q

Firebase有一个名为GeoFire的开源库,该库:

  1. 使您可以轻松地在Firebase中存储地理位置(必须具有经纬度)作为地理哈希。
  2. 提供查询功能,以便您可以获得指定位置最大距离内的节点。

我建议您签出iOS版本的GeoFire

2020-07-07