質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

3回答

2090閲覧

緯度と経度を引数に渡すと、住所が帰ってくる関数を作成したい!

Tommy2020

総合スコア18

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

1クリップ

投稿2020/09/06 08:52

編集2020/09/06 08:53

Swiftで緯度と経度を引数に渡すと、住所が帰ってくる関数を、サイトを参考に作成しています。
いわゆる逆ジオコーディングです。
しかし、returnでエラーが出てしまいます。
全く原因が分かりません。
分かる方教えてください!

func reverseGeoCording(lat: Int,long: Int) -> String{ // 住所を取得したい位置情報を宣言 var address : String let location = CLLocation(latitude: CLLocationDegrees(lat), longitude: CLLocationDegrees(long)) // 位置情報から住所を取得 CLGeocoder().reverseGeocodeLocation(location) { placemarks, error in guard let placemark = placemarks?.first, error == nil else { return } // 市区町村より下の階層が出力 print(placemark.name!) // 都道府県 print(placemark.administrativeArea!) // なんとか郡とかがあれば(ない場合もあるのでnull回避) print(placemark.subAdministrativeArea ?? "") // 市区町村 print(placemark.locality!) var address = placemark.administrativeArea! + placemark.locality! + placemark.name! } return address }

イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

上記のメソッドのマニュアルを見ると下記のような記述があります。

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/06 10:55

編集2020/09/06 10:56
TsukubaDepot

総合スコア5086

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Tommy2020

2020/09/07 11:06

ご回答ありがとうございます。 クロージャーの使い方をよく存じておりませんでした。 行いたいことができるようになりました。 また、Int,Doubleの件もありがとうございます。 正確に位置を割り出すことができるようになりました。 また機会ありましたらよろしくお願いします。
guest

0

その出ているメッセージを翻訳にでもかけて読んでみればどうでしょう。
みるかぎり、文法的にaddressの代入文がおかしいのでエラーになってしまっている、とみえますが

投稿2020/09/06 09:57

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

エラーメッセージは指摘もらってるとおり、
初期化しないで使われているから、だと思うのですが、

初期値入れるなどしてエラーを回避したとしても、
アドレスを取ってくる処理が非同期処理だと思うので
戻り値では返せないのではないかなと思います。

ぐぐったら過去質問に似たような話が出てたので、参考にどうぞ。

https://teratail.com/questions/87656

投稿2020/09/06 10:51

tanishi_a

総合スコア484

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問