使用 mapKit Swift (miles/km) 显示与用户的距离
Display the distance from user with mapKit Swift (miles/km)
我一直在尝试在 tableView 上显示距离,但无法实现。这个问题来自这个问题:CLLocationDistance conversion。我检查了距离。在我的 Location
class:
中使用这个函数
// Get distance
func distance(to location: CLLocation) -> CLLocationDistance {
return location.distance(from: self.location)
}
如何获取用户当前位置:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
let span:MKCoordinateSpan = MKCoordinateSpanMake(0.01, 0.01)
let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, span)
mapView.setRegion(region, animated: true)
// Add a lastUserLocation to LocationManager and update it every time that the delegate receives a new location
LocationManager.shared.lastUserLocation = locations.last
LocationManager.shared.sortLocationsInPlace()
self.mapView.showsUserLocation = true
}
LocationManager 中的排序功能:
func getSortedLocations(userLocation: CLLocation) -> [Location] {
return locations.sorted { (l1, l2) -> Bool in
return l1.distance(to: userLocation) < l2.distance(to: userLocation)
}
}
func sortLocationsInPlace() {
if let validLocation = lastUserLocation {
locations.sort { (l1, l2) -> Bool in
return l1.distance(to: validLocation) < l2.distance(to: validLocation)
}
}
}
cellForRowAt:
var sortedLocations = [Location]()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "locationCell", for: indexPath)
let location = sortedLocations[indexPath.row]
cell.textLabel?.text = location.name
return cell
}
更新
里面 Location
class:
class Location {
var name: String
var latitude: Double
var longitude: Double
var location:CLLocation {
return CLLocation(latitude: latitude, longitude: longitude)
}
init?(json: JSON) {
guard let name = json["name"] as? String, let latitude = json["latitude"] as? Double, let longitude = json["longitude"] as? Double else { return nil }
self.name = name
self.latitude = latitude
self.longitude = longitude
}
func distance(to location: CLLocation) -> CLLocationDistance {
return location.distance(from: self.location)
}
}
考虑到你的代码,我做了一些假设:
- 您的
sortedLocations
数组有不同的位置,您从 JSON 或其他任何地方提取。
- 您在加载数据之前调用 startUpdatingLocation() 或类似的地方。
- 您正在接收更新
didUpdateLocations
。
- 您的
LocationManager
在名为 locations
的变量中保存了所有位置的有序副本,您在 didUpdateLocations
. 中订购的变量
考虑到,我知道你想做的是根据参考位置显示你的sortedLocations
排序.
缺少的是在收到您的用户位置后更新您的 UITableView
数据。您有两个主要选择:
- 仅在
didUpdateLocations
检索到您的第一个用户位置后才加载您的 UITableView
。
- 要在获得新位置后强制执行
UITableView
更新,方法是在 didUpdateLocations
中调用 tableView.reloadData()
。这将在您每次收到位置更新时重新绘制您的列表,并按位置对它们进行排序。
但是,在任何一种情况下,您都需要替换 cellForRow
文本来显示您的距离,而不是 location.name
:
// Distance in meters
cell.textLabel?.text = String(location.distance(to: LocationManager.shared.lastUserLocation!))
// Distance in miles
cell.textLabel?.text = String(location.distance(to: LocationManager.shared.lastUserLocation!)*0.00062137)
并且更新你的didUpdateLocations
:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.last {
let span:MKCoordinateSpan = MKCoordinateSpanMake(0.01, 0.01)
let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, span)
mapView.setRegion(region, animated: true)
// Add a lastUserLocation to LocationManager and update it every time that the delegate receives a new location
LocationManager.shared.lastUserLocation = location
LocationManager.shared.sortLocationsInPlace()
sortedLocations = LocationManager.shared.locations
tableView.reloadData()
self.mapView.showsUserLocation = true
}
}
使用您当前的代码,您正在将所有距离与一个 self.location
变量进行比较,该变量显然没有在任何地方初始化。
我一直在尝试在 tableView 上显示距离,但无法实现。这个问题来自这个问题:CLLocationDistance conversion。我检查了距离。在我的 Location
class:
// Get distance
func distance(to location: CLLocation) -> CLLocationDistance {
return location.distance(from: self.location)
}
如何获取用户当前位置:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
let span:MKCoordinateSpan = MKCoordinateSpanMake(0.01, 0.01)
let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, span)
mapView.setRegion(region, animated: true)
// Add a lastUserLocation to LocationManager and update it every time that the delegate receives a new location
LocationManager.shared.lastUserLocation = locations.last
LocationManager.shared.sortLocationsInPlace()
self.mapView.showsUserLocation = true
}
LocationManager 中的排序功能:
func getSortedLocations(userLocation: CLLocation) -> [Location] {
return locations.sorted { (l1, l2) -> Bool in
return l1.distance(to: userLocation) < l2.distance(to: userLocation)
}
}
func sortLocationsInPlace() {
if let validLocation = lastUserLocation {
locations.sort { (l1, l2) -> Bool in
return l1.distance(to: validLocation) < l2.distance(to: validLocation)
}
}
}
cellForRowAt:
var sortedLocations = [Location]()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "locationCell", for: indexPath)
let location = sortedLocations[indexPath.row]
cell.textLabel?.text = location.name
return cell
}
更新
里面 Location
class:
class Location {
var name: String
var latitude: Double
var longitude: Double
var location:CLLocation {
return CLLocation(latitude: latitude, longitude: longitude)
}
init?(json: JSON) {
guard let name = json["name"] as? String, let latitude = json["latitude"] as? Double, let longitude = json["longitude"] as? Double else { return nil }
self.name = name
self.latitude = latitude
self.longitude = longitude
}
func distance(to location: CLLocation) -> CLLocationDistance {
return location.distance(from: self.location)
}
}
考虑到你的代码,我做了一些假设:
- 您的
sortedLocations
数组有不同的位置,您从 JSON 或其他任何地方提取。 - 您在加载数据之前调用 startUpdatingLocation() 或类似的地方。
- 您正在接收更新
didUpdateLocations
。 - 您的
LocationManager
在名为locations
的变量中保存了所有位置的有序副本,您在didUpdateLocations
. 中订购的变量
考虑到,我知道你想做的是根据参考位置显示你的sortedLocations
排序.
缺少的是在收到您的用户位置后更新您的 UITableView
数据。您有两个主要选择:
- 仅在
didUpdateLocations
检索到您的第一个用户位置后才加载您的UITableView
。 - 要在获得新位置后强制执行
UITableView
更新,方法是在didUpdateLocations
中调用tableView.reloadData()
。这将在您每次收到位置更新时重新绘制您的列表,并按位置对它们进行排序。
但是,在任何一种情况下,您都需要替换 cellForRow
文本来显示您的距离,而不是 location.name
:
// Distance in meters
cell.textLabel?.text = String(location.distance(to: LocationManager.shared.lastUserLocation!))
// Distance in miles
cell.textLabel?.text = String(location.distance(to: LocationManager.shared.lastUserLocation!)*0.00062137)
并且更新你的didUpdateLocations
:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.last {
let span:MKCoordinateSpan = MKCoordinateSpanMake(0.01, 0.01)
let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, span)
mapView.setRegion(region, animated: true)
// Add a lastUserLocation to LocationManager and update it every time that the delegate receives a new location
LocationManager.shared.lastUserLocation = location
LocationManager.shared.sortLocationsInPlace()
sortedLocations = LocationManager.shared.locations
tableView.reloadData()
self.mapView.showsUserLocation = true
}
}
使用您当前的代码,您正在将所有距离与一个 self.location
变量进行比较,该变量显然没有在任何地方初始化。