2017-08-29 7 views
1

これはかなり一般的な話題です。私は研究を行っていますが、クロージャー/補完ハンドラーの周りに頭を抱えようとしています。ジオコーディングを完了してから次のシーンに切り替えるswift 3/xcode

場所が入力されているシーンがあります。ユーザーが提出すると、次のシーンへの送信からセグがあります。ジオコードが非同期であることは認識していますが、次のシーンに移動する前にエラーが発生した場合に備えて、ジオコードを完成させたいと思います。

このサイトにはいくつかの短い記事がありますが、本質的なものはありません。

以下は、失敗した補完ハンドラの試みです。エラーがある場合はアラートを取得しますが、アラートがポップアップする前に次のシーンに移動します。

func geocodeAddress (completion: @escaping() ->()) { 
    let geoCoder = CLGeocoder() 
    var coords: CLLocationCoordinate2D? 

    address = locationData(addressString) 

    geoCoder.geocodeAddressString((address)!, completionHandler: {(placemarks: [CLPlacemark]?, error: Error?) -> Void in    
     if error != nil { 
      self.alertGeocodeError()   
     }   
     if let placemark = placemarks?[0]{ 
      // Convert the address to a coordinate 
      let location = placemark.location 
      coords = location!.coordinate 

      completion() 
      self.performSegue(withIdentifier: "locationToConfirmSegue", sender: coords)   
      }  
     })  
    } 

override func prepare (for segue: UIStoryboardSegue, sender: Any?){ 
    geocodeAddress{ 
     if let destinationVC = segue.destination as? ConfirmController { 
      destinationVC.coords = sender as! CLLocationCoordinate2D 
     } 
    } 
} 

@esapingもあまり得意ではありませんし、どんなアドバイスも素晴らしいでしょう。

ありがとうございました。

答えて

1

prepare(for segue:)は、self.performSegueに電話すると自動的にシステムから呼び出されるため、geocodeAddressprepare(for segue:)と呼ぶべきではありません。

ジオコーダの補完ハンドラの内側から順に処理する必要がある場合は、geocodeAddress関数からクロージャを返す必要はありません。performSegueを直接呼び出すことができます。

completionHandlersは、非同期関数から値を返すために使用できます。ジオコーディングはAppleのサーバー上で行われるため、すぐには返されない非同期関数ですが、実行に時間がかかり、実行が終了する前に関数が戻ります。一方、完了ハンドラは、実行が実際に終了すると呼び出されます。

func geocodeAddress() { 
    let geoCoder = CLGeocoder() 
    var coords: CLLocationCoordinate2D? 

    address = locationData(addressString) 

    geoCoder.geocodeAddressString((address)!, completionHandler: {(placemarks: [CLPlacemark]?, error: Error?) -> Void in    
     if error != nil { 
      self.alertGeocodeError()   
     }   
     if let placemark = placemarks?[0]{ 
      // Convert the address to a coordinate 
      let location = placemark.location 
      coords = location!.coordinate 

      self.performSegue(withIdentifier: "locationToConfirmSegue", sender: coords)   
     }  
    })  
} 

override func prepare (for segue: UIStoryboardSegue, sender: Any?){ 
    if let destinationVC = segue.destination as? ConfirmController { 
     destinationVC.coords = sender as! CLLocationCoordinate2D 
    } 
} 
関連する問題