1

私はDispatchGroup.enter()とleave()を使ってヘルパークラスのreverseG async関数を処理しています。問題は明らかです、私はmainViewControllerのオブジェクトを使用して、mainViewControllersのヘルパクラスのdispatchGroup.leave()を呼び出しています!それを行う方法はありますか?swift 3 DispatchGroup leaveはヘルパークラス関数で呼び出されるとクラッシュする

同じコードは、メインビューコントローラでreverseGが宣言されているときに機能します。メインビューコントローラから

class Geo { 
    var obj = ViewController() 

    static func reverseG(_ coordinates: CLLocation, _ completion: @escaping (CLPlacemark) ->()) { 
     let geoCoder = CLGeocoder() 
     geoCoder.reverseGeocodeLocation(coordinates) { (placemarks, error) in 
      if let error = error { 
       print("error: \(error.localizedDescription)") 
      } 
      if let placemarks = placemarks, placemarks.count > 0 { 
       let placemark = placemarks.first! 
       completion(placemark) // set ViewController's properties 
      } else { 
       print("no data") 
      } 
      obj.dispatchGroup.leave() // ** ERROR ** 
     } 
    } 


} 

関数呼び出し

dispatchGroup.enter() 
Geo.reverseG(coordinates, setValues) // completionHandler: setValues 

dispatchGroup.notify(queue: DispatchQueue.main) { 

    // call another function on completion 

} 
+0

すべての 'leave'コールは、関連する' enter'コールを持っていなければなりません。あなたが最初の 'enter'と呼ばれることなく、' leave'呼び出す場合ここで問題となっているのは、あなたがいくつかのグループで 'enter'を呼び出しているということですが、' reverseG'は 'ViewController'の他のインスタンスで' leave'を呼び出しています。 'DispatchGroup'をパラメータを 'reverseG'メソッドに渡します。グループを離れるべきではなく、 'reserveG'が呼び出す完了ハンドラの中に' leave'コールを入れてください。 – Rob

+0

まあ、すでにそれをして、それは働いた。ありがとう –

答えて

0

すべてleaveコールは、関連enter電話を持っている必要があります。最初にenterと呼ぶことなくleaveに電話すると、クラッシュします。ここでの問題は、一部のグループでenterを呼び出していることですが、はViewControllerという別のインスタンスではleaveを呼び出しています。私はあなたのreverseGメソッドにパラメータとしてDispatchGroupを渡すことをお勧めします。または、より良い、reverseGは、グループを離れるべきではなく、reserveGが呼び出す完了ハンドラ内にleaveコールを入れます。

dispatchGroup.enter() 
Geo.reverseG(coordinates) { placemark in 
    defer { dispatchGroup.leave() } 

    guard let placemark = placemark else { return } 

    // use placemark here, e.g. call `setValues` or whatever 
} 

dispatchGroup.notify(queue: DispatchQueue.main) { 
    // call another function on completion 
} 

そして

class Geo { 
    // var obj = ViewController() 

    static func reverseG(_ coordinates: CLLocation, completion: @escaping (CLPlacemark?) -> Void) { 
     let geoCoder = CLGeocoder() 
     geoCoder.reverseGeocodeLocation(coordinates) { placemarks, error in 
      if let error = error { 
       print("error: \(error.localizedDescription)") 
      } 
      completion(placemarks?.first) 

      // obj.dispatchGroup.leave() // ** ERROR ** 
     } 
    } 

} 

これは、結合あまりしっかりと自分のクラスを維持、アプリの1つのレベルでDispatchGroupロジックを保持します(例:ジオコーダは、ビューコントローラがディスパッチを使用するかどうかを知る必要はありません。グループかどうか)。

ただ、1つのコールしかない場合は、ディスパッチグループを使用している理由がわかりません。通常は、補完ハンドラ内で呼び出したものをすべて入れて、コードをさらに単純化します。一般的に一連の呼び出しを行う場合は、グループのみを使用します。 (おそらく、コードスニペットを単純化しただけで、複数の呼び出しを実際に行っている場合は、ディスパッチグループが意味をなさないかもしれませんが、やはり並行ジオコード要求を行ってはいけません。まったく。

+0

私はちょうど別のクラスの逆ジオ関数を必要とし、プロパティを設定する(コールバック関数を呼び出さない)メインクラスの目印を使います。 function1の結果はfunction2に必要で、function3にはf1とf2の結果が必要です。メインクラスのプロパティのみを設定するために補完ハンドラを使用しています。 f1はf2で使用されるプロパティを設定します。 –

+0

は完了ハンドラと同じです... f1(完了:f2(完了:f3))?? f1とf2の結果を使用するためにf3が必要な場合 –

+0

これ以上の文脈がなければ言うことは難しいです。ここでディスパッチグループの質問に回答したことを考えれば、私たちがあなたのしていることを示す広い文脈で新しい質問を投稿することをお勧めします。動作しているコードがあり、デザインに関するフィードバックが必要な場合は、おそらくhttp://codereview.stackexchange.comがより良いフォーラムです。または、それがうまくいかない場合は、Stack Exchangeに関する別の質問を投稿してください。いずれにしても、その他の質問へのリンクをコメントに追加してください。しかし、私たちは既にあなたの元のディスパッチグループの質問からあまりにも遠く離れています... – Rob

0

関数呼び出しでパラメータとしてdispatchGroup渡され、それが働いた。

Geo.reverseG(coordinates, dispatchGroup, setValues) 
関連する問題