使用mapKit Swift显示与用户的距离(英里/公里) [英] Display the distance from user with mapKit Swift (miles/km)

查看:124
本文介绍了使用mapKit Swift显示与用户的距离(英里/公里)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直试图在tableView上显示距离,但无法实现.该问题来自以下问题: CLLocationDistance转换.我已经检查了距离.在我的Location类中使用此功能:

I have been attempting to display the distance on a tableView but I am unable to get it to happen. This question follows up from this question: CLLocationDistance conversion. I have checked the distance. Using this function in my Location class:

// Get distance
func distance(to location: CLLocation) -> CLLocationDistance {
    return location.distance(from: self.location)
}

如何获取用户当前位置:

How I get the users current 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中排序功能:

Sort function in 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:

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

推荐答案

考虑到您的代码,我在做一些假设:

Considering your code, I am making some assumptions:

  1. 您的sortedLocations数组具有从 JSON 或其他提取的位置.
  2. 您在加载您的文件之前,先致电 startUpdatingLocation()或类似名称.数据.
  3. 您正在didUpdateLocations接收更新.
  4. 您的LocationManager将您所有位置的有序副本保存在名为locations的变量中,该变量是您在didUpdateLocations内部订购的变量.
  1. Your sortedLocations array has different locations that you extracted from a JSON or whatever.
  2. You call startUpdatingLocation() or similar somewhere before loading your data.
  3. You are receiving updates in your didUpdateLocations.
  4. Your LocationManager keeps an ordered copy of all your locations in a variable called locations, the one you are ordering inside didUpdateLocations.

考虑过,据我了解,您想要做的是显示根据参考位置排序的sortedLocations.

That considered, what I understand you want to do is to display your sortedLocations ordered according to a reference location.

缺少的是一旦收到您的用户位置,便更新您的UITableView数据.您有两个主要选择:

What is missing is to update your UITableView data once your user location is received. You have two main options:

  1. 仅当您已经由didUpdateLocations检索到您的第一个用户位置时,才加载UITableView.
  2. 在获取新位置后通过在didUpdateLocations中调用tableView.reloadData()强制执行UITableView更新.每当您收到位置更新信息时,都会重新绘制您的列表,并按位置对它们进行排序.
  1. To only load your UITableView once you have already your first user location retrieved by didUpdateLocations.
  2. To force a UITableView update once you get a new location, by calling tableView.reloadData() inside didUpdateLocations. This will redraw your list every time you receive a location update, sorting them by location.

但是,在任何情况下,您都需要替换cellForRow文本以显示距离而不是location.name:

However, in any of those cases you need to replace your cellForRow text to display your distance instead of 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变量进行比较,该变量显然没有在任何地方初始化.

With your current code you are comparing all distances with a self.location variable that its not being initialised anywhere apparently.

这篇关于使用mapKit Swift显示与用户的距离(英里/公里)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆