【问题标题】:How to set tableview to place stores nearest to my current location using geopoint in Cloud Firestore?如何使用 Cloud Firestore 中的地理点设置 tableview 以放置离我当前位置最近的商店?
【发布时间】:2020-02-24 22:57:37
【问题描述】:

我想要做的是使用 Cloud Firestore 中的 Geopoint 在离我当前位置最近的商店组织我的单元格

我已经查看了整个堆栈,但我找不到如何在 ViewController 中设置 tableview 以使用 Cloud Firestore 中的地理点显示离我当前位置最近的花店

这是我目前必须设置的数据以传递给 VC,以便它将数据从 Firestore 组织到离我当前位置最近的商店

下面是我的 Firestore 中的集合图像和我的 ViewController 的图像,以了解我的应用程序是如何设置的

import Foundation
import UIKit

class Store {
    var id: String
    var storeName: String
    var imageUrl: String
    var location: ??

    init(id: String,
         storeName: String,
         imageUrl: String,
         location:??) {                                              //

        self.id = id
        self.storeName = storeName
        self.imageUrl = imageUrl
        self.location = location                                    //
    }

    convenience init(dictionary: [String : Any]) {
        let id = dictionary["id"] as? String ?? ""
        let storeName = dictionary["storeName"] as? String ?? ""
        let imageUrl =  dictionary["imageUrl"] as? String ?? ""
        let location =  dictionary["location"] as? String ?? ""    //

        self.init(id: id,
                  storeName: storeName,
                  imageUrl: imageUrl,
                  location: location)                              //
    }

}

import UIKit
import CoreLocation
import Firebase
import FirebaseFirestore

class ViewController: UIViewController, CLLocationManagerDelegate {

    var locationManager: CLLocationManager?

    @IBOutlet weak var tableView: UITableView!

    var stores: [Store] = []

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

    override func viewDidLoad() {
        super.viewDidLoad()

        locationManager = CLLocationManager()
        locationManager?.delegate = self
        locationManager?.requestWhenInUseAuthorization()

        tableView.dataSource = self
        tableView.delegate = self

        fetchStores { (stores) in
            self.stores = stores
            self.tableView.reloadData()
        }

    }

    func fetchStores(_ completion: @escaping ([Store]) -> Void) {
        let ref = Firestore.firestore().collection("storeName")
            ref.addSnapshotListener { (snapshot, error) in
            guard error == nil, let snapshot = snapshot, !snapshot.isEmpty else {
                return
            }
            completion(snapshot.documents.compactMap( {Store(dictionary: $0.data())} ))
        }
    }

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        if status == .authorizedWhenInUse {
            if CLLocationManager.isMonitoringAvailable(for: CLBeaconRegion.self){
                if CLLocationManager.isRangingAvailable() {
                    // do Stuff
                }
            }
        }
    }
}

【问题讨论】:

  • 看起来ViewController 没有一个名为stores 的属性。如果有,能否将其包含在代码中以便我们查看?
  • 抱歉错字刚刚更新了我的代码,现在它确实具有 stores 属性

标签: swift firebase uitableview google-cloud-firestore location


【解决方案1】:

我相信这个答案应该有效,尽管我可能遗漏了一些东西。

您要做的是在Store 中创建location 属性,类型为CLLocationCoordinate2D。这需要导入CoreLocation。您还想添加一个名为distanceFromUser 的属性,它使用CLLocation.distance(from:) 方法来查找用户当前位置和商店位置之间的距离(以米为单位):

import Foundation
import UIKit
import CoreLocation
import Firebase
import FirebaseFirestore

class Store {
    var id: String
    var storeName: String
    var imageUrl: String
    var location: CLLocationCoordinate2D
    var distanceFromUser: Double

    init(id: String,
         storeName: String,
         imageUrl: String,
         location: CLLocationCoordinate2D) {

        self.id = id
        self.storeName = storeName
        self.imageUrl = imageUrl
        self.location = location  
        self.distanceFromUser = (CLLocationManager().location?.distance(from: CLLocation(latitude: location.latitude, longitude: location.longitude)))!
    }

    convenience init(dictionary: [String : Any]) {
        let id = dictionary["id"] as? String ?? ""
        let storeName = dictionary["storeName"] as? String ?? ""
        let imageUrl =  dictionary["imageUrl"] as? String ?? ""

        //We now have to convert Firestore's "location" property from a GeoPoint to a CLLocationCoordinate2d
        let geoPoint = dictionary["location"] as! GeoPoint
        let latitude = geoPoint.latitude
        let longitude = geoPoint.longitude

        let location =  CLLocationCoordinate2D(latitude: latitude!, longitude: longitude!)

        self.init(id: id,
                  storeName: storeName,
                  imageUrl: imageUrl,
                  location: location)
    }
}

然后,您需要在ViewControllerviewDidLoad 中按distanceFromUser 对您的商店进行排序:

import UIKit
import CoreLocation
import Firebase
import FirebaseFirestore

class ViewController: UIViewController, CLLocationManagerDelegate {

    ...

    override func viewDidLoad() {
        super.viewDidLoad()

        locationManager = CLLocationManager()
        locationManager?.delegate = self
        locationManager?.requestWhenInUseAuthorization()

        tableView.dataSource = self
        tableView.delegate = self

        fetchStores { (stores) in
            self.stores = stores.sorted(by: { $0.distanceFromUser < $1.distanceFromUser })
            self.tableView.reloadData()
        }

    }

    ...

}

【讨论】:

  • 同样,您可以在self.distanceFromUser = (CLLocationManager().location?.distance(from: CLLocation(latitude: location.latitude, longitude: location.longitude)))! 之后的行中添加print("look here!", self.distanceFromUser) 并检查打印到控制台的内容。它应该打印多个距离。
  • 如果位置在 Firestore 上不是唯一的,您将无法在前端按距离排序。如果您将 Firestore locations 设置为其唯一坐标,那么 Swift 代码应该可以工作。
  • 好的,问题是我们没有正确地将 Geopoint 转换为 CLLocationCoordinate2d,因此所有商店默认为 0 度 N,0 度 W。让我看看如何施放 Geopoint 并回复您。
  • 我对@9​​87654336@ 进行了更改,尝试一下,让我知道它是否适合您。看来我们需要将此值转换为GeoPoint,我以为它作为String 存储在Firestore 上。
  • 您可能必须在 Store 文件中添加 import Firebaseimport FirebaseFirestore
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-12
  • 1970-01-01
  • 2018-06-11
  • 1970-01-01
相关资源
最近更新 更多