2点間の距離とsort

はじめに

mapKitを使ってピン表示などをさせる時に距離が近い順に処理をしたい用件が出てきたのでメモとして残しておく。

以下のような構造体のリストを現在位置と比べて近い順にsortする。

struct AmusementParkPoint {
    let title: String
    let location: CLLocation
}

2点間の距離

CLLocationがdistanceというメソッドを保持しているのでそれを使えば簡単に距離計算を行うことが可能です。

単位はメートルで帰ってきます

let distance = CLLocation(latitude: 35.4858947 ,
                          longitude: 138.7800076).distance(from: CLLocation(latitude: 35.6359322 ,
                                                                            longitude: 139.8786311))
print(distance)
//100983.66487796529

func distance(from location: CLLocation) -> CLLocationDistance

https://developer.apple.com/documentation/corelocation/cllocation/1423689-distance

距離の近い順にsortする

private func sortDistance(amusementParkPointList: [AmusementParkPoint], currentLocation: CLLocation) -> [AmusementParkPoint] {
    return  amusementParkPoitList.sorted(by: { location1, locations2 in
        let dist1 = location1.location.distance(from: currentLocation)
        let dist2 = locations2.location.distance(from: currentLocation)
        return dist1 < dist2
    })
}

コード一覧

import UIKit
import CoreLocation

struct AmusementParkPoint {
    let title: String
    let location: CLLocation
}

class ViewController: UIViewController {
    var locationManager:CLLocationManager!
    
    let amusementParkPoitList = [
        AmusementParkPoint(title: "富士急ハイランド",
                           location: CLLocation(latitude: 35.4858947 ,
                                                 longitude: 138.7800076)),
        AmusementParkPoint(title: "東京ディズニーランド",
                           location: CLLocation(latitude: 35.6359322 ,
                                                 longitude: 139.8786311)),
        AmusementParkPoint(title: "ユニバーサル・スタジオ・ジャパン|USJ",
                            location: CLLocation(latitude: 34.6656995 ,
                                                  longitude: 135.432666))]

    override func viewDidLoad() {
        super.viewDidLoad()
        
        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.requestAlwaysAuthorization()

        locationManager.desiredAccuracy = kCLLocationAccuracyBest
    }
}

extension ViewController: CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        switch status {
        case .notDetermined:
            manager.requestWhenInUseAuthorization()

        case .restricted, .denied:
            break
            
        case .authorizedAlways, .authorizedWhenInUse:
            manager.startUpdatingLocation()
            locationManager.startUpdatingLocation()
        default:
            break

        }
    }
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        
        guard let location = locations.first else {
            return
        }
        
        let sortAmusementList = sortDistance(amusementParkPointList: amusementParkPoitList,
                                             currentLocation: location)
        
        sortAmusementList.forEach{
            print($0.title)
        }
    }
    
    private func sortDistance(amusementParkPointList: [AmusementParkPoint], currentLocation: CLLocation) -> [AmusementParkPoint] {
        return  amusementParkPoitList.sorted(by: { location1, locations2 in
            let dist1 = location1.location.distance(from: currentLocation)
            let dist2 = locations2.location.distance(from: currentLocation)
            return dist1 < dist2
        })
    }
}

参考文献

Swiftで配列をソート(sort)する方法 : (昇順・降順・逆順)

[iOS] 地図アプリを作る – 現在地から近い順に並べる