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

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

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

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

Q&A

解決済

1回答

1617閲覧

ジオコーディングした緯度経度をグローバル変数に代入する方法。

mimizuku123

総合スコア12

Swift

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

0グッド

0クリップ

投稿2020/11/12 17:36

前提・実現したいこと

住所から緯度経度を出力し、グローバル変数に緯度経度を保存しようと考えています。
そこで、CLGeocoder().geocodeAddressStringを利用して緯度経度を出力しましたが
グローバル変数に緯度経度を代入することができません。

下記ソースコードの
viewDidLoad()内のprint("3",eventAddressCoordinate)にて
出力がnilではなく、緯度経度が入っている状態で出力する方法をご教授いだだけると幸いです。

また、よろしければ処理の順番が
ソースコードに記載された順番ではなく、
print("2",eventAddressCoordinate)
print("3",eventAddressCoordinate)
print("1",eventAddressCoordinate)
というように、前後する理由をご教授いただけると幸いです。

該当のソースコード

swift

1import UIKit 2import MapKit 3 4var eventAddressCoordinate:CLLocationCoordinate2D? 5 6class ViewController: UIViewController { 7 8 override func viewDidLoad() { 9 super.viewDidLoad() 10 geocode() 11 print("3",eventAddressCoordinate) 12 } 13 14 func geocode(){ 15 let testKey:String? = "東京都千代田区千代田1−1" 16 guard let searchKey = testKey else { print("testKey = nil"); return } 17 let geocoder = CLGeocoder() 18 geocoder.geocodeAddressString(searchKey) { (placemarks, error) in 19 guard let unwrapPlacemark = placemarks else { return } 20 guard let firstPlacemark = unwrapPlacemark.first else { return } 21 guard let location = firstPlacemark.location else { return } 22 eventAddressCoordinate = location.coordinate 23 print("1",eventAddressCoordinate) 24 } 25 print("2",eventAddressCoordinate) 26 } 27 28} 29 30

デバックエリアの内容

2 nil 3 nil 1 Optional(__C.CLLocationCoordinate2D(latitude: 35.6837221, longitude: 139.7535985))

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

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

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

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

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

guest

回答1

0

ベストアンサー

Swift

1 geocoder.geocodeAddressString(searchKey) { (placemarks, error) in

上記のメソッドは非同期に実行されるメソッドとなります。

Submits a forward-geocoding request using the specified string.

上記のリファレンスには

Discussion

This method submits the specified location data to the geocoding server asynchronously and returns.

と記述してありますので、指定した searckKey での検索は非同期に行われ、その処理結果が completionHandler で指定したクロージャに渡されるようになっています。

したがって、クロージャを渡したからと言ってそれが即時に実行されるわけではなく、サーバに住所を送り、ジオコーディングに成功(あるいは失敗)した時点でクロージャが実行される仕組みとなっています。

なので、実行結果が

2 nil
3 nil
1 Optional(__C.CLLocationCoordinate2D(latitude: 35.6837221, longitude: 139.7535985))

という具合になってしまっています。

求められた実行結果を元に、スコープ外の変数に対して何らかの処理を行いたいのであれば、その処理をさらにクロージャとして渡すようにするか、プロパティオブザーバの利用、あるいはオブザーバパターンなどの利用が必要となってきます。

以下はクロージャを渡す例となりますので、参考にしていただければと思います。
playground でも動くようになっています。

厳密にエラー処理を行なっているわけではありませんので、必要に応じてエラー処理を書き換えていただければと思います。

また、geocodeAddressStringに渡すクロージャはメインスレッドで実行されるようですので(リファレンスより)、geocode 内の DispatchQueue は必要ないかもしれません。

Swift

1import UIKit 2import MapKit 3 4geocode { location, error in 5 guard let location = location else { 6 if let error = error { 7 print(error.localizedDescription) 8 } else { 9 print("Unknown error.") 10 } 11 return 12 } 13 14 // 緯度軽度を表示 15 print(location) 16 17} errorHandler: { 18 print("error") 19} 20 21func geocode(completionHandler: @escaping (CLLocationCoordinate2D? , Error?) -> (), errorHandler: @escaping () -> ()){ 22 let testKey:String? = "東京都千代田区千代田1−1" 23 //let testKey:String? = "あり得ない住所" 24 25 guard let searchKey = testKey else { 26 errorHandler() 27 return 28 29 } 30 31 let geocoder = CLGeocoder() 32 geocoder.geocodeAddressString(searchKey) { (placemarks, error) in 33 guard let unwrapPlacemark = placemarks else { 34 DispatchQueue.main.async { 35 // エラーを返す 36 completionHandler(nil, error) 37 } 38 return 39 } 40 41 // ジオコーディングが成功したら少なくとも住所は一つ入っていると想定されているので、 42 // 強制アンラップしても問題ないかもしれない 43 // 以下公式ドキュメントより 44 // For most geocoding requests, this array should contain only one entry. 45 let firstPlacemark = unwrapPlacemark.first! 46 let location = firstPlacemark.location! 47 48 DispatchQueue.main.async { 49 // 取得した住所を返す 50 completionHandler(location.coordinate, nil) 51 } 52 } 53}

投稿2020/11/13 00:15

TsukubaDepot

総合スコア5086

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問