はじめに
つい先日、iOSアプリ開発をしている最中に緯度経度を取得して地図上にピンを置くという処理を作っていました。
その際に取得される緯度経度が10進数ではなく、60進数の緯度経度が返ってきていました。
地図上の指定した緯度経度にピンを置く場合、Double型(10進数)で指定する必要があります。(CLLocationCoordinate2DMake)
あまり使われない形だからなのか、60進数→10進数に変換する方法を調べても出てこなかった内容だったので共有します。
10進数と60進数の緯度経度の形
まず最初に緯度経度の10進数と60進数の形の違いについてです。
// こっちは60進数。
let sexagesimalScaleLat = "35°00′00.000″"
let sexagesimalScaleLon = "138°00′00.000″"
// こっちは10進数。アプリ開発社の方々がよく見る形かな?
let decimalScaleLat = "35.000000"
let decimalScaleLon = "138.000000"
// そして今回私が遭遇した60進数の緯度経度はこっち
let anotherSexagesimalScaleLat = "35/00/00.000"
let anotherSexagesimalScaleLon = "138/00/00.000"
60進数→10進数に変換する
以上の事を踏まえて60進数を10進数の形に変換します。その計算方法は簡単で
「度」はそのままで、「分」を60、「秒」を3,600で割りそれらを足すと計算完了です。
とても簡単ですね。では残すはその計算をする処理を実装するのみとなりました。
解決策
今回はメソッドを作るのも良かったですが、
・複数のクラスで使う
・APIからはStringが渡される
・度分秒は"/"で区切られる
という条件があったのでStringのextensionで60進数→10進数の計算をするgetterメソッドを定義します。
extension String {
var latlonValue: String {
// 文字列を"/"で区切る。
let split = self.components(separatedBy: "/")
// 期待する60進数の形でなければ元の文字列を返して終了する
if split.count != 3 { return self }
// 分、秒を計算してから度を足して結果を返す
// これらを一つにまとめると「計算式が長い」とエラーが出ます。
let minute = (Double(split[1]) ?? 0) * 60
let second = ((Double(split[2]) ?? 0) + minute) / 3600
let result = (Double(split[0]) ?? 0) + second
return result.description
}
}
// 使い方
let anotherSexagesimalScaleLat = "35/00/00.000"
let anotherSexagesimalScaleLon = "138/00/00.000"
let convertLat = anotherSexagesimalScaleLat.latlngValue
let convertLon = anotherSexagesimalScaleLon.latlonValue
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2DMake(Double(convertLat) ?? 0, Double(convertLon) ?? 0)
これで問題なく地図に表示できるようになりました!
まとめ
今回は"/"で区切られたり他のクラスで使う事が分かっていたのでStringのextensionで対応しましたが
**(考えたくないけど)**区切られる文字が固定じゃなかったり特定のクラスでのみ使うのであればprivateなメソッドを定義した方が良いかな〜と思います。
結論
サーバー側で10進数で返すようにしてくれたらそれが一番!