title: Synchronise multiple web service calls in serial order in swift
body: <p>I am hitting a web service url 10 times and getting the response. I am using <code>Alamofire</code> and <code>SwiftyJSON</code>. This is my controller code</p>
  
  <pre><code>class ViewController: UIViewController {
  
      let dispatchGroup = DispatchGroup()
  
      var weatherServiceURL = "http://samples.openweathermap.org/data/2.5/weather?q=London,uk&amp;appid=b6907d289e10d714a6e88b30761fae22"
  
      override func viewDidLoad() {
          super.viewDidLoad()
          start()
      }
  
      func start() {
          weatherService()
          dispatchGroup.notify(queue: .main) {
              print("All services complete")
          }
      }
  
      func weatherService() {
          for i in 1...10 {
              dispatchGroup.enter()
              APIManager.apiGet(serviceName: self.weatherServiceURL, parameters: ["counter":i]) { (response:JSON?, error:NSError?, count:Int) in
                  if let error = error {
                      print(error.localizedDescription)
                      return
                  }
                  guard let response = response else { return }
                  print("\n\(response) \n\(count) response\n")
                  self.dispatchGroup.leave()
              }
          }
      }
  }
  </code></pre>
  
  <p>This is my Service Handler class code</p>
  
  <pre><code>class APIManager: NSObject {
  
      class func apiGet(serviceName:String,parameters: [String:Any]?, completionHandler: @escaping (JSON?, NSError?, Int) -&gt; ()) {
          Alamofire.request(serviceName, method: .get, parameters: nil, encoding: URLEncoding.default, headers: nil).responseJSON { (response:DataResponse&lt;Any&gt;) in
  
              switch(response.result) {
              case .success(_):
                  if let data = response.result.value{
                      let json = JSON(data)
                      completionHandler(json,nil, parameters!["counter"] as! Int)
                  }
                  break
  
              case .failure(_):
                  completionHandler(nil,response.result.error as NSError?, parameters!["counter"] as! Int)
                  break
              }
          }
      }
  }
  </code></pre>
  
  <p>I am sending a counter key with the index of for loop just to keep the track of response of which index is coming back. But the response is not coming in serial order. We can expect 3rd response before the 2nd and 1st response. This is because the API call with <code>APIManager.apiGet</code> function call is asynchronous and is escaping and therefore continuing the for loop.</p>
  
  <p>Also I used the dispatchQueue</p>
  
  <pre><code>let dispatchQueue = DispatchQueue(label: "com.test.Queue", qos: .userInteractive)
  </code></pre>
  
  <p>and converted the function as:</p>
  
  <pre><code>func weatherService() {
      for i in 1...10 {
          dispatchGroup.enter()
          dispatchQueue.async {
              APIManager.apiGet(serviceName: self.weatherServiceURL, parameters: ["counter":i]) { (response:JSON?, error:NSError?, count:Int) in
                  if let error = error {
                      print(error.localizedDescription)
                      return
                  }
                  guard let response = response else { return }
                  print("\n\(response) \n\(count) response\n")
                  self.dispatchGroup.leave()
              }
          }
      }
  }
  </code></pre>
  
  <p>Same result as the service calling code is asynchronous. If we make </p>
  
  <pre><code>dispatchQueue.sync {
     //service call 
  }
  </code></pre>
  
  <p>then also we will not get the response in serial order since the networking call in async and dispatchQueue assumes the task is completed.</p>
  
  <p>Condition is to hit the service in async manner only without freezing the UI. If I hit the service is synchronous manner, then I get my desired result. But blocking main thread is not at all acceptable.</p>
  
  <p>I can manage this thing using array or some global bool variables, but I don't want to use them. Is there any other way I can get response in serial order in which it is called? Any help or hint is appreciated.</p>