如何使用 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)
}
}
然后,您需要在 ViewController
的 viewDidLoad
:
中按 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()
}
}
...
}
我想做的是使用 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)
}
}
然后,您需要在 ViewController
的 viewDidLoad
:
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()
}
}
...
}