如何使用 Cloud Firestore 中的地理点设置 tableview 以放置离我当前位置最近的商店?

How to set tableview to place stores nearest to my current location using geopoint in Cloud Firestore?

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

我查看了整个堆栈,但找不到如何在 ViewController 中设置表格视图以使用 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: [=11=].data())} ))
        }
    }

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

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

您需要做的是在 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: { [=11=].distanceFromUser < .distanceFromUser })
            self.tableView.reloadData()
        }

    }

    ...

}