📍

MKDirectionsで公共交通機関(transit)の所要時間を取得する

に公開

はじめに

先日、MapKitのMKDirectionsを使用した実装でハマった点があったので、備忘録として記事にします。MKDirectionsを使用すると、出発地から目的地へのルートや距離・所要時間を計算できます。
https://developer.apple.com/documentation/mapkit/mkdirections

公共交通機関(transit)を指定するとエラーになる

実現したいことは、現在地から目的地への公共交通機関利用時の所要時間を取得することです。MKDirectionscalculateメソッドを使用することでそれを実現できそうだと分かったので、試してみました。

https://developer.apple.com/documentation/mapkit/mkdirections/calculate(completionhandler:)

以下の様に書いてみました。

// 現在地の座標はあらかじめ取得しておく
let currentPlacemark = MKPlacemark(coordinate: currentLocation.coordinate)

// 今回は'東京駅'を目的地に指定
let destinationCoordinate = CLLocationCoordinate2D(latitude: 35.681236, longitude: 139.767125)
let destinationPlacemark = MKPlacemark(coordinate: destinationCoordinate)

// リクエストの作成
let request = MKDirections.Request()
request.source = MKMapItem(placemark: currentPlacemark) // 出発地
request.destination = MKMapItem(placemark: destinationPlacemark) // 目的地
/*
 移動手段を指定
 - automobile: 車・バイク
 - walking: 徒歩
 - transit: 公共交通機関
 - any: あらゆる交通手段
 */
request.transportType = .transit // '公共交通機関'を指定

let directions = MKDirections(request: request)
directions.calculate { response, error in
    // ルート情報が返却される
    guard let route = response?.routes.first, error == nil else {
        return
    }
    // 所要時間を出力
    let minutes = Int(route.expectedTravelTime / 60)
    print("所要時間は\(minutes)分")
}

このように書いて実行してみましたが、Error Domain=MKErrorDomain Code=5 "(null)"というエラーが返却されてしまいました。.transitの代わりに.automobile.walkingを指定するとルート情報や距離、所要時間を取得できる為、すぐに原因が分かりませんでした。

公共交通機関(transit)は所要時間(ETA)のみをサポートしている

出発時間を未来日付にしてみたり、transportTypeに.anyを指定することで.transitを含むルート情報が返却されないか試しましたが、いずれも上手くいきませんでした。

そこでMKDirectionsTransportTypetransitのドキュメントを改めて見返してみたところ、こんな記載がありました。

This type is only supported for estimating time of arrival.

https://developer.apple.com/documentation/mapkit/mkdirectionstransporttype/transit

つまり、transportTypeが.transitの場合は、ルート情報(MKRouteの配列)を返すことができない様です。また同時に、所要時間(ETA, Estimating Time of Arrival)であれば.transitもサポートされているということが分かりました。これを取得すれば所要時間が分かりそうです。

公共交通機関(transit)の所要時間を取得する方法

MKDirectionsculculateメソッドの他にも、calculateETAというメソッドも持っています。こちらを使用すれば所要時間を計算することが出来ます。

https://developer.apple.com/documentation/mapkit/mkdirections/calculateeta(completionhandler:)

以下の様に実装すると、.transitの場合でも所要時間を計算することが出来ました。レスポンスには目的地までの所要時間を示すexpectedTravelTimeが含まれています。

// リクエストの作成
let request = MKDirections.Request()
request.source = MKMapItem(placemark: currentPlacemark) // 出発地
request.destination = MKMapItem(placemark: destinationPlacemark) // 目的地
request.transportType = .transit // '公共交通機関'を指定

let directions = MKDirections(request: request)
directions.calculateETA { response, error in
    guard let response, error == nil else { return }
    // 所要時間を出力
    print("所要時間は\(Int(round(response.expectedTravelTime / 60)))分")
}

また上記のドキュメントによると、calculateETAの計算時間はcalculateよりもかなり早い為、.transitに限らずルート情報が不要で所要時間のみを知りたい場合は、こちらを使った方が良さそうです。

Travel-time estimates take much less time to generate than directions, so use this method in situations where you want a time estimate only.

さいごに

今回はMKDirectionsで公共交通機関の所要時間を取得する際にハマった点について書きました。
この記事が同じように困っている方の役に立つものであればうれしいです!

Livesense Engineers

Discussion