上記のメソッドのマニュアルを見ると下記のような記述があります。
Discussion
This method submits the specified location data to the geocoding server asynchronously and returns. When the request completes, the geocoder executes the provided completion handler on the main thread.
説明にもある通り、逆ジオコーディングは非同期に行われるため、クロージャの処理が完了する前に呼び出した関数そのものが終了してしまいます。
また、クロージャの中で宣言したaddress
と、クロージャ外(関数のトップレベル)で宣言したaddress
は同名でもスコープが違う変数のため、仮にクロージャ内でaddress
に値を代入してもクロージャ外のaddress
に影響を与えることはありません。
最終行のreturn
で出ているエラーは、address
という変数が宣言後一度も値を代入されることなく使われているため出ているエラーです。
諸々のことを考慮すると、非同期処理で得たデータを使うためには、一般的にはクロージャとして処理したいブロック(あるいは関数)を渡すような処理にすることが多いかと思います。
たとえば、ご提示いただいた関数は次にように書き換え、実行することが可能となります。
この内容であれば、Playground でそのまま実行することが可能です。
逆ジオコーディングに失敗した特の処理までは考慮していませんので、その辺りは質問者さんで適宜調整していただければと思います。
Swift
1import CoreLocation
2
3func reverseGeoCording(lat: Double,long: Double, completion: @escaping (String) -> Void ) {
4
5 // 住所を取得したい位置情報を宣言
6 let location = CLLocation(latitude: CLLocationDegrees(lat), longitude: CLLocationDegrees(long))
7 // 位置情報から住所を取得
8 CLGeocoder().reverseGeocodeLocation(location) { placemarks, error in
9 guard let placemark = placemarks?.first, error == nil else { return }
10 // 市区町村より下の階層が出力
11 print(placemark.name!)
12 // 都道府県
13 print(placemark.administrativeArea!)
14 // なんとか郡とかがあれば(ない場合もあるのでnull回避)
15 print(placemark.subAdministrativeArea ?? "")
16 // 市区町村
17 print(placemark.locality!)
18
19 let address = placemark.administrativeArea! + placemark.locality! + placemark.name!
20
21 // クロージャの実行
22 completion(address)
23 }
24}
25
26reverseGeoCording(lat: 35.6809591 , long: 139.7673068, completion: { address in
27 // 何らかの処理
28 print("クロージャでの処理: ", address)
29})
余談ですが、reverseGeoCording(lat:lon:completion:)
の最初2つの引数はInt
ではなくDouble
の方が好ましいかと思います。
例えば、緯度だと1度異なると約120km異なるため、Int
だと精度が悪く、よっぽどの田舎でないと役に立たないかと思います。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/09/07 11:06