Дми*_*аев 2 userlocation ios firebase swift firebase-realtime-database
无法弄清楚如何对用户附近的地址进行自动排序。我不明白从哪里开始以及如何编写代码。
\n\n我的firebase中有地址。地址的类型为字符串(不是纬度/经度)。例子:
\n\n"\xd0\x9c\xd0\xbe\xd1\x81\xd0\xba\xd0\xb2\xd0\xb0, \xd0\xad\xd0\xbb\xd0\xb5\xd0\xba\xd1\x82\xd1\x80\xd0\xbe\xd0\xb7\xd0\xb0\xd0\xb2\xd0\xbe\xd0\xb4\xd1\x81\xd0\xba\xd0\xb0\xd1\x8f, 21"\n"\xd0\x9c\xd0\xbe\xd1\x81\xd0\xba\xd0\xb2\xd0\xb0, \xd0\x90\xd1\x80\xd0\xb1\xd0\xb0\xd1\x82, \xd0\xa1\xd1\x82\xd0\xb0\xd1\x80\xd0\xbe\xd0\xba\xd0\xbe\xd0\xbd\xd1\x8e\xd1\x88\xd0\xb5\xd0\xbd\xd0\xbd\xd1\x8b\xd0\xb9 \xd0\xbf\xd0\xb5\xd1\x80\xd0\xb5\xd1\x83\xd0\xbb\xd0\xbe\xd0\xba, \xd0\xb4\xd0\xbe\xd0\xbc 43"\n"\xd0\x9c\xd0\xbe\xd1\x81\xd0\xba\xd0\xb2\xd0\xb0, \xd1\x83\xd0\xbb\xd0\xb8\xd1\x86\xd0\xb0 1-\xd1\x8f \xd0\x91\xd1\x83\xd1\x85\xd0\xb2\xd0\xbe\xd1\x81\xd1\x82\xd0\xbe\xd0\xb2\xd0\xb0, \xd0\xb4\xd0\xbe\xd0\xbc 12/11, \xd0\xba\xd0\xbe\xd1\x80\xd0\xbf\xd1\x83\xd1\x81 53"\nRun Code Online (Sandbox Code Playgroud)\n\n我知道什么需要使用firebase 的查询,但是如何使用查询,我现在不明白。
\n\n这是我的代码:
\n\nclass PhotoStudiosViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIScrollViewDelegate {\n\n @IBOutlet weak var tableView: UITableView!\n\n var theStudios: [Studio] = []\n\n var studiosRef: DatabaseReference!\n\n override func viewWillAppear(_ animated: Bool) {\n super.viewWillAppear(true)\n\n tableView.estimatedRowHeight = 475\n tableView.rowHeight = UITableViewAutomaticDimension\n\n loadDataFromFirebase()\n\n }\n\n func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {\n\n return theStudios.count\n }\n\n func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {\n let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! PhotoStudiosTableViewCell\n\n cell.addressLabel.text = theStudios[indexPath.row].studioAddress\n\n return cell\n }\n\n func loadDataFromFirebase() {\n\n studiosRef = Database.database().reference(withPath: "Addresses")\n\n let time = DispatchTime.now() + 0.5 \n\n studiosRef.observe(.value, with: { (snapshot) in\n\n DispatchQueue.main.asyncAfter(deadline: time) {\n\n for imageSnap in snapshot.children {\n\n let studioObj = Studio(snapshot: imageSnap as! DataSnapshot)\n\n self.theStudios.append(studioObj)\n\n }\n\n self.tableView.reloadData()\n\n }\n\n })\n\n}\n\n\n\nclass Studio {\n\n var ref: DatabaseReference! \n var studioAddress: String = ""\n\n init(snapshot: DataSnapshot) {\n\n ref = snapshot.ref\n studioName = snapshot.key\n\n let value = snapshot.value as! NSDictionary \n\n studioAddress = value["address"] as? String ?? "---"\n\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n如何使用firebase中的数据对用户附近的地址进行自动排序?
\n这是一个复杂的过程,需要多个步骤。我将尝试解释这些步骤,但您必须做相当多的工作才能将其变成有效的解决方案。
首先:像您拥有的那样的地址字符串不是位置。计算机无法比较两个这样的字符串并可靠地知道它们之间的距离。
因此,您要做的第一件事就是将地址转换为更可靠的位置指示,即转换为纬度和经度(又名纬度/经度)。将地址转换为纬度/经度的过程称为地理编码。这并不是一门精确的科学,但有很多服务在地理编码方面非常擅长。
在此地理编码过程结束时,您将获得每个地址的纬度/经度组合。这又把问题带回了数学,这是一门更加精确的科学。
接下来,您需要比较每个地址的纬度/经度并计算它们之间的距离。这是一门相对精确的科学,如果你愿意忽略两极附近的误差和类似的事情的话。
不幸的是,Firebase 实时数据库本身只能对单个属性进行排序/过滤。由于位置由两个属性(纬度和经度)组成,因此如果没有一些魔法,它就无法过滤位置。
幸运的是,有人想出了一种将纬度/经度信息转换为单个字符串的方法,称为geohash。例如:旧金山的 Google 办公室位于 lat/lon 37.7900515,-122.3923805,翻译为 geohash 9q8yyz。山景城的 Googleplex 位于 lat/lon 37.4219999,-122.0862515,翻译为 geohash 9q9hvu。
与您开始使用的地址不同,geohash 非常具有可比性。引用(链接的)维基百科解释:
附近的地方[有]相似的前缀。共享前缀越长,两个地方越接近。
在上面的两个示例中,您可以看到这两个位置彼此相对较近,因为它们都以9q
Firebase 有一个名为 GeoFire 的开源库,它:
我建议您查看iOS 版本的 GeoFire。
| 归档时间: |
|
| 查看次数: |
2632 次 |
| 最近记录: |