2017-01-29 7 views
0

私は即座に閉鎖するのが新しく、注釈を閉鎖から戻す方法を知りました。非同期であるため、外部の配列が適切なタイミングで満たされないことがわかります。このクロージャからデータを戻すにはどうすればよいですか?

完了ハンドラのようなものを使用する必要がありますか?それ、どうやったら出来るの?これのベストプラクティスは何ですか?コールバックを持つ関数はdidupdateLocationから呼び出されます。

fileprivate func getGooglePoisForCurrentLocation(centerLatitude: Double, centerLongitude: Double, delta: Double, count: Int) -> Array<GMAnnotation> 
     { 
      var annotations: [GMAnnotation] = [] 

      placesClient.currentPlace(callback: { (placeLikelihoods, error) -> Void in 
       if let error = error { 
        print("Current Place error: \(error.localizedDescription)") 
        return 
       } 

       if let likelihoodList = placeLikelihoods { 
        for likelihood in likelihoodList.likelihoods { 

         let annotation = GMAnnotation() 
         let place = likelihood.place 

         annotation.location = CLLocation(latitude: place.coordinate.latitude, longitude: place.coordinate.longitude) 

         annotations.append(annotation) 
        } 


       } 
      }) 

      return annotations; ====> EMPTY 

答えて

3

(あなたがそうするようにDispatchQueue.main.asyncを使用することができます)、このような呼び出しはメインスレッドで実行されなければならないことに注意してください。たとえば、このデータをテーブルビューに表示する場合は、tableView.reloadData()(またはその兄弟メソッドの1つ)を呼び出して、実際にテーブルを更新する必要がありますデータが利用可能です。あなたはそれを呼び出すと

fileprivate func getGooglePoisForCurrentLocation(centerLatitude: Double, centerLongitude: Double, delta: Double, count: Int, closure: @escaping (Array<GMAnnotation>) -> Void) { 
    var annotations: [GMAnnotation] = [] 

    placesClient.currentPlace(callback: { (placeLikelihoods, error) -> Void in 
     if let likelihoodList = placeLikelihoods { 
      for likelihood in likelihoodList.likelihoods { 

       let annotation = GMAnnotation() 
       let place = likelihood.place 

       annotation.location = CLLocation(latitude: place.coordinate.latitude, longitude: place.coordinate.longitude) 

       annotations.append(annotation) 
      } 
      closure(annotations) 
     } 
    }) 
} 

、あなたのテーブルビューのデータソースを更新し、その後、テーブルビューをリロードします:ここにあなたの関数はクロージャである

getGooglePoisForCurrentLocationclosure(closure: { (annotations) -> Void in 
    tableViewDataSourceArray = annotations 
    tableView.reloadData() 
}) 

注意点として、この例では、特にないですsafe - エラーチェックはなく、戻り値の型はオプションではありません.API呼び出しが失敗した場合、クラッシュする可能性があります。以下は同じ関数のより堅牢なバージョンで、エラーと適切な戻り値の型を扱います:

enum PlacesResult { 
    case success(Array<GMAnnotation>) 
    case error(Error) 
} 

fileprivate func getGooglePoisForCurrentLocation(centerLatitude: Double, centerLongitude: Double, delta: Double, count: Int, closure: @escaping (PlacesResult) -> Void) { 
    var annotations: [GMAnnotation] = [] 

    placesClient.currentPlace(callback: { (placeLikelihoods, error) -> Void in 
     if let error = error { 
      print("Current Place error: \(error.localizedDescription)") 
      closure(PlacesResult.error(error)) 
     } 
     if let likelihoodList = placeLikelihoods { 
      for likelihood in likelihoodList.likelihoods { 
       let annotation = GMAnnotation() 
       let place = likelihood.place 
       annotation.location = CLLocation(latitude: place.coordinate.latitude, longitude: place.coordinate.longitude) 
       annotations.append(annotation) 
      } 
      closure(PlacesResult.success(annotations)) 
     } else { 
      closure(PlacesResult.error(Error())) 
      // something else went wrong but we still want this to call the closure. 
     } 
    }) 
} 
1

まあ、currentPlace呼び出しは非同期である、したがって、あなたはすぐにあなたのgetGooglePoisForCurrentLocation機能には何も返すことができません。

あなたははこのような何かを行うことができ、ニーズに応じて:のViewController

  • コールいくつかのUIのリフレッシュコード他(のようなtableView.reloadDataか気にいら中のプライベートインスタンス変数で

    • 店の注釈ViewController)を使用してUIを更新します。はい、あなたはあなたの関数に@escapingクロージャを追加する必要があります
  • 関連する問題