【问题标题】:Display a list of the closest locations to the user on a table在表格上显示离用户最近的位置列表
【发布时间】:2017-10-13 18:26:59
【问题描述】:

我可以在桌子上显示位置列表。但现在我想根据当前位置对其进行排序。

这是我显示位置的方式:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "locationCell", for: indexPath)

    let location = LocationManager.shared.locations[indexPath.row]
    cell.textLabel?.text = location.name
    return cell
}

我试图在我从https://stackoverflow.com/a/35200027/6362735 获得的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)
    }
}

显示当前位置:

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)

    self.mapView.showsUserLocation = true
}

【问题讨论】:

    标签: ios swift sorting cllocationmanager


    【解决方案1】:

    您现在需要做的是按距离对LocationManager.shared.locations 进行排序,并将用户的位置作为参数传递。你可以把这两个放在你的LocationManager中。

    func getSortedLocations(userLocation: CLLocation) -> [Location] {
        return locations.sorted { (l1, l2) -> Bool in
            return l1.distance(to: userLocation) < l2.distance(to: userLocation)
        }
    }
    
    func sortLocationsInPlace(userLocation: CLLocation) {
        locations.sort { (l1, l2) -> Bool in
            return l1.distance(to: userLocation) < l2.distance(to: userLocation)
        }
    }
    

    对位置进行排序后,致电tableView.reloadData(),您的行应按距离排序。

    在何处使用此代码取决于您的应用的结构。

    如果您使用按钮进行过滤,您可以在操作中对您的位置进行排序:

    @IBAction func orderByDistance() {
        sortLocationsInPlace(userLocation: yourUsersLocation)
        tableView.reloadData()
    }
    

    如果您希望您的数据始终有序,您可以在首次创建tableView 时对其进行排序。在你的UIViewController

    let sortedLocations: [Location]()
    
    override func viewDidLoad() {
        sortedLocations = getSortedLocations(userLocation: yourUsersLocation)
    }
    

    然后您可以将 dataSource 方法更改为:

    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
    }
    

    另外,请记住,您可以使用sortsorted,具体取决于您是要就地排序还是创建已排序的副本时间>。有关 CLLocationManager 如何工作的更多信息,您应该阅读here

    【讨论】:

    • 感谢您的回复。但是你能详细说明我会在我的应用上调用它的位置吗?
    • 这取决于您的应用程序的结构。如果你有一个按钮或触发过滤操作的东西,你应该把它放在那里。如果您希望您的位置始终按距离排序,您可以将其放在 TableView 的控制器中,例如viewDidLoad。我会用这两种情况更新答案。
    • 我在参数中输入了什么?当我使用你的排序功能时,它只会说:Missing argument for parameter 'to' in call。它期待一个CLLocation
    • 又更新了,我错过了你的函数distance有一个to:参数,对不起!
    • 现在我收到此错误Cannot convert value of type 'Location' to expected argument type 'CLLocation'
    【解决方案2】:

    使用distance 函数将结果数组按left &lt; right 排序:

    locations.sorted(by: { $0.distance(to: myLocation) < $1.distance(to: myLocation) } )
    

    这是一个您可以测试的工作示例:

    import Foundation
    import CoreLocation
    
    struct Location {
    
        var latitude: Double
        var longitude: Double
        var location:CLLocation {
            return CLLocation(latitude: latitude, longitude: longitude)
        }
    
        init(lat: Double, long: Double) {
            self.latitude = lat
            self.longitude = long
        }
    
        func distance(to location: CLLocation) -> CLLocationDistance {
            return location.distance(from: self.location)
        }
    }
    
    let locations: [Location] = [
        Location(lat: 61.98573, long: 27.57300),
        Location(lat: -62.98404, long: 62.81190),
        Location(lat: -3.18446, long: 107.07900)]
    
    let myLocation = CLLocation(latitude: 73.30051, longitude: -141.88647)
    
    let locationsClosestToMe = locations.sorted(by: { $0.distance(to: myLocation) < $1.distance(to: myLocation) } )
    

    证明功能(单元测试):

    print(locationsClosestToMe.map { $0.distance(to: myLocation) } )
    
    /*
    [
      4970593.6601553941, 
      11003159.607318919, 
      18486409.053517241
    ]
    */
    

    【讨论】:

    • 感谢您的回复。我有点困惑如何使用myLocation 作为当前位置而不是硬编码位置?我的代码显示了我如何获取当前位置。但它是CLLocationCoordinate2DMake 而不是CLLocation,就像您的方法需要的那样。另外,如何获取要在我的表格上显示的数据?
    • 看看stackoverflow.com/a/25698536/1214800?它应该做你需要的。无论哪种方式,您都使用与标准 CLLocation 对象初始化相同的 lat/long 值初始化 2DMake。
    猜你喜欢
    • 1970-01-01
    • 2020-11-27
    • 2016-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多