1

I try use nested DispatchGroup, there is my code :

 class TranslateService {
      private let myGroup = DispatchGroup()
      func translateText(text:[String],closure:@escaping ((_ success:String?,_ error:Error?) -> Void)) {

        var translateString: String = ""
        var responseError: Error?

        for index in 0...text.count - 1 {

          let urlString = "https://translate.yandex.net/api/v1.5/tr.json/translate?key=trnsl.1.1.20171105T134956Z.795c7a0141d3061b.dc25bae76fa5740b2cdecb02396644dea58edd24&text=\(text[index])&lang=fa&format=plain&options=1"
          if let allowString = Utilities.shareInstance.getQueryAllowedString(url: urlString) {
            if let url = URL(string:allowString){
                myGroup.enter()
              Alamofire.request(url).responseJSON { response in
                guard let responseData = response.data else {
                  self.myGroup.leave()
                  return
                }
                do {
                  let json = try JSONSerialization.jsonObject(with: responseData, options: [])
                  if let res = json as? [String:Any] {
                    if let code = res["code"] as? Int {
                      if code == 200 {
                        if let textArr = res["text"] as? [AnyObject] {
                          let flattArr = Utilities.shareInstance.flatStringMapArray(textArr)
                          if flattArr.count > 0 {
                            translateString += "،" + flattArr[0]
                          }
                        }
                      }
                    }
                     self.myGroup.leave()
                  }
                }catch {
                  responseError = error
                 self.myGroup.leave()
                }
              }
              self.myGroup.notify(queue: .main) {
                print("Finished all requests.")
                print(translateString)
                closure(translateString, responseError)
              }
            }
          }
        }
      }
    }

    class AddressService {
  private let translateService: TranslateService = TranslateService()
  private let myGroup = DispatchGroup()
  func fetchAddressFromGeographicalLocation(latitude: Double, longitude: Double,closure:@escaping ((_ success:String,_ name:String,_ error:Error?) -> Void)) {

    var address: String = ""
    let name: String = ""
    var responseError: Error?
    if let url = URL(string:"https://maps.googleapis.com/maps/api/geocode/json?latlng=\(latitude),\(longitude)&key=AIzaSyAdEzHZfZWyjLMuuW92w5fkR86S3-opIF0&language=fa&region=IR&locale=fa"){
       self.myGroup.enter()
      Alamofire.request(url).responseJSON { response in

        guard let responseData = response.data else {
          self.myGroup.leave()
          return
        }
        do {
          let json = try JSONSerialization.jsonObject(with: responseData, options: [])
          if let addressDic = json as? [String:Any] {
            if let result = addressDic["results"] as? [AnyObject] {
              if result.count > 0 {
                let flattRes = Utilities.shareInstance.flatMapArray(result)
                let item = flattRes[0]
                address = item["formatted_address"] as? String ?? ""
                var res = address
                if res.isContainEnglishCharachter {
                  self.myGroup.enter()
                  let resArr = res.components(separatedBy: ",")
                  var all : [String] = []
                  for item in resArr {
                    if item != " " {
                      all.append(item)
                    }}
                  self.translateService.translateText(text: all, closure: {stringAdd,error in
                    self.myGroup.enter()
                    if error != nil {
                      self.myGroup.leave()
                    }else {
                      address = stringAdd ?? ""
                      self.myGroup.leave()
                    } })
                }else {
                  self.myGroup.leave()
                }
              }
            }
          }
        }catch {
          responseError = error
          self.myGroup.leave()
        }
        self.myGroup.notify(queue: .main) {
          // print("Finished all requests.")
          closure(address, name, responseError)
          }
      }
    }
  }
}

All I want is that the myGroup I put in the class AddressService waiting for the myGroup that I put in the class TranslateService. but now self.myGroup.notify not call in the AddressService class, So closure not work. How can solve this problem, Thank you for all the answers.

ava
  • 1,148
  • 5
  • 15
  • 44

1 Answers1

0

I think you are over complicating it.

If I understood a bit, what you want to do is the following:

  • Get an address from the Address service.
  • Translate some words of that address, one by one, using the translation service.

When using the Address service there is only one call being done, so there is no need to use Dispatch Groups at this point. Dispatch Groups are used to synchronize more than one async call.

For your Translation service you can make good use of the Dispatch groups, since you are doing calls to the service inside a for loop. The problem here is, that the implementation is slightly wrong. You are setting the notification block inside the for loop, and it should be outside, so that it gets only triggered once, when all the calls inside the loop are done.

So move this block outside the for loop in the Translation service:

self.myGroup.notify(queue: .main) {
            print("Finished all requests.")
            print(translateString)
            closure(translateString, responseError)
          }

Now "Finished all requests." will only be printed once, when all requests are done.

In the address service you do not need dispatch groups at all. Just wait until the completion block is called.

self.translateService.translateText(text: all, closure: {stringAdd,error in
      Everything is done here already.
}
crom87
  • 1,141
  • 9
  • 18
  • thanks for reply, I did that at first , remove dispatch from AddressService, But in this case before call TranslateService closure , AddressService closure call and Untranslated sentence show in UI. – ava Jun 19 '18 at 04:18