首页 > 解决方案 > 如何使用 Cloud Firestore 中的地理点设置 tableview 以放置离我当前位置最近的商店?

问题描述

我想要做的是使用 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
                }
            }
        }
    }
}

在此处输入图像描述

标签: swiftfirebaseuitableviewgoogle-cloud-firestorelocation

解决方案


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

您要做的是将location属性Store设置为 type 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)
    }
}

然后,您需要distanceFromUserViewController's中对商店进行排序viewDidLoad

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()
        }

    }

    ...

}

推荐阅读