2017-02-14 15 views
1

緯度と経度を持ちながら都市の名前を取得しようとしています。 モデルクラスLocationでは、CLGeocoder(CoreLocationの一部)に付属のreverseGeocodeLocation(location: , completionHandler:) funcを使用しています。終了ハンドラは非同期で、まだ終わっていなかったので、非同期完了ハンドラからデータを取得

func getLocationName() { 

    let geoCoder = CLGeocoder() 
    let location = CLLocation(latitude: currentLatitude, longitude: currentLongitude) 

    geoCoder.reverseGeocodeLocation(location, completionHandler: { placemarks, error in 
     guard let addressDict = placemarks?[0].addressDictionary else { 
      return 
     } 

     if let city = addressDict["City"] as? String { 
      self.currentCity = city 
      print(city) 
     } 
     if let zip = addressDict["ZIP"] as? String { 
      print(zip) 
     } 
     if let country = addressDict["Country"] as? String { 
      print(country) 
     } 
    }) 
} 

しかし、ViewControllerで、getLocationName()を実行した後、location.currentCityは、nilです。

location.currentCityにアクセスできるように、完了ハンドラが実行されていることを確認するにはどうすればよいですか?

+0

だけでアクセス 'location.currentCity' **で**完了ハンドラまたは非同期にデータを返すために、')( 'getLocationNameに別の完了ハンドラを追加。 – vadian

+0

「完了ハンドラが実行を終了していることを確認してください」というのではなく、 'completionHandler'の' location.currentCity'で何をしたいのですか? –

+0

@vadian私は 'location.currentCity'にアクセスする必要があります。コントローラ、(Locationクラスの外)UIを更新しました。別の補完ハンドラを追加してモデルクラス内のUIを更新しない方が良いでしょうか? 新しい補完ハンドラをどのように実装する必要があるかのサンプルコードを提供できますか? –

答えて

2

クロージャをあなたのgetLocationNameの関数パラメータである は、reverseGeocodeLocationクロージャ内で呼び出すことができます。あなたのViewControllerで

func updateLocation(currentCity : String) -> Void 
{ 
    print(currentCity) 
} 

func getLocationName(callback : @escaping (String) -> Void) 
{ 

    let geoCoder = CLGeocoder() 
    let location = CLLocation(latitude: currentLatitude, longitude: currentLongitude) 

    geoCoder.reverseGeocodeLocation(location, completionHandler: { placemarks, error in 
    guard let addressDict = placemarks?[0].addressDictionary else { 
     return 
    } 


    if let city = addressDict["City"] as? String 
    { 
     self.currentCity = city 
     callback(city) 

     print(city) 
     } 
     if let zip = addressDict["ZIP"] as? String { 
     print(zip) 
     } 
     if let country = addressDict["Country"] as? String { 
     print(country) 
     } 
    }) 
} 

は...

getLocationName(callback: updateLocation) 
+0

内部のコールバックが何であるか分かりません... しかし、あなたは私にいくつかの考えを与えました: コールバックの中で 'currentCity'をどうすれば設定できますか? コールバックは完了ハンドラの後にのみ実装されるため、これを行うことができます。右? –

+0

完了ハンドラが終了するとコールバックが呼び出されます。私の例を参照して、updateLocation関数内でcurrentCityを設定することができ、その関数をViewControllerに追加することができます。 –

+0

にはエラーが多数あります: 'func getLocationName(コールバック:(location:CLLocation))' - 要素ラベルを持つ単一要素タプルを作成できません。 'callback(location)'で - 非関数型 'CLLocation'の値を呼び出すことはできません と 'print(location。currentCity) ' - タイプ' CLLocation 'の値にメンバー' currentCity 'がありません –

0

私はlocation.currentCityが使用されている関数を作成し、あなたのコードは次のように見える場合は、完了ハンドラので

からこの関数を呼び出します。

func foo() { 
    var location 
    getLocationName() 
    print(location.currentcity) // nil 
} 

に変更し、それを:

func foo() { 
    var location 
    getLocationName() 
} 

func bar() { 
    print(location.currentcity) // someplace 
} 

と完了ハンドラからの呼び出しbar()

+0

ありがとうございました。 しかし、bar()は別のクラス(ViewController内)にあります。私はbar()のUIを更新したいと思います。 LocationControllerのインスタンスを作成し、Locationモデルファイルで 'updateUI()'を実行する必要がありますか? –

関連する問題