按照距离firebase的用户位置附近的距离排序数组

时间:2017-11-18 10:27:55

标签: ios swift firebase firebase-realtime-database userlocation

无法弄清楚如何在用户附近自动排序地址。我无法理解从哪里开始以及如何编写代码。

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

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

我知道什么需要使用来自firebase的查询,但是如何使用查询,我现在还不明白。

这是我的代码:

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 中的数据在用户附近制作自动排序地址?

1 个答案:

答案 0 :(得分:1)

这是一个复杂的过程,需要多个步骤。我会尝试解释这些步骤,但你必须做一些工作才能把它变成一个有效的解决方案。

天气预报

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

因此,首先要做的是将地址转换为更可靠的位置指示,即纬度和经度(a.k.a. lat / lon)。将地址转换为lat / lon的过程称为geocoding。这不是一个真正的科学,但有很多服务在这个地理编码位上相当不错。

在此地理编码过程结束时,您将为每个地址设置一个lat / lon组合。这将问题重新纳入数学,这是一门更为精确的科学。

Geoqueries

接下来,您需要比较每个地址的纬度/经度和calculate the distance between them。如果你愿意忽略极点附近的不准确以及类似的事情,那么 是一个相对精确的科学。

不幸的是,Firebase实时数据库本身只能对单个属性进行排序/过滤。由于某个位置包含两个属性(纬度和经度),因此无法在没有魔法的情况下对其进行过滤。

幸运的是,有人提出了将纬度/经度信息转换为单个字符串的方法,称为geohash。例如:Google office in San Francisco位于纬度/经度37.7900515,-122.3923805,转换为geohash 9q8yyz。 Mountain View中的Googleplex位于纬度/经度37.4219999,-122.0862515,转换为geohash 9q9hvu

与您开始使用的地址不同,geohashes具有非常好的可比性。引用(链接)维基百科的解释:

  

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

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

开头

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

  1. 可以轻松地将Firebase中的位置(必须具有lat / lon)存储为地理位置。
  2. 提供查询功能,以便您可以获取与指定位置的最大距离之内的节点。
  3. 我建议您查看iOS version of GeoFire