0

I have these 2 requests that I want completed before reloading the table view(table view depends on both of them).

I tried like below, but it does not work.

Request 1 gets completed, then the table view reloads before everything being done in request 2.

DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async {
        //1. request 1:
        self.serverRequestAuth("/request1")
        //2. request 2:
        self.serverRequestAuth("/request2")
            DispatchQueue.main.async{
                //3. reload the table view
                self.tableView.reloadData()
            }
    }

How I should I proceed?

Mention: serverRequestAuth contains the server request, the parsing of the json, the parsing of the dictionary inside it.

The method serverRequestAuth:

func serverRequestAuth(_ requestName: String){
    let requestNameEscaped = requestName.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!


    var request = NSMutableURLRequest()
    request = NSMutableURLRequest(url: URL(string: "\(self.view.getServerPath())\(requestNameEscaped)")!, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 5)

    request.httpMethod = "GET"
    request.setValue(self.view.getAuth(), forHTTPHeaderField: "Authorization")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

    let task = URLSession.shared.dataTask(with: request as URLRequest) {data, response, err in
        if data != nil {
            if let dictionary = self.parseJSONData(data!) {
                self.parseDictionary(dictionary, typeOfRequest: requestName)
            }
        }
    }
    task.resume()
}
asheyla
  • 3,175
  • 5
  • 18
  • 34

3 Answers3

0

Try to use DispatchSemaphore

func serverRequestAuth(_ requestName: String){
    let requestNameEscaped = requestName.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!

    let semaphore = DispatchSemaphore(value: 0);
    var request = NSMutableURLRequest()
    request = NSMutableURLRequest(url: URL(string: "\(self.view.getServerPath())\(requestNameEscaped)")!, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 5)

    request.httpMethod = "GET"
    request.setValue(self.view.getAuth(), forHTTPHeaderField: "Authorization")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

    let task = URLSession.shared.dataTask(with: request as URLRequest) {data, response, err in
        if data != nil {
            if let dictionary = self.parseJSONData(data!) {
                self.parseDictionary(dictionary, typeOfRequest: requestName)
                semaphore.signal();
            }
        }
    }
    task.resume()
    semaphore.wait(timeout: .distantFuture)
}
aahmetbas
  • 64
  • 7
  • 1
    I tried all answers, this was the one that worked for me, with the mention that "semaphore.wait(timeout: .distantFuture)" was giving me a warning: "Result of call to 'wait(timeout:)' is unused" and I changed it like this: "_ = semaphore.wait(timeout: .distantFuture)" – asheyla Nov 24 '16 at 10:21
0

Try this:

func serverRequestAuth(_ requestName: String, control:@escaping (_ check : Bool)-> Void){
    let requestNameEscaped = requestName.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!


    var request = NSMutableURLRequest()
    request = NSMutableURLRequest(url: URL(string: "\(self.view.getServerPath())\(requestNameEscaped)")!, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 5)

    request.httpMethod = "GET"
    request.setValue(self.view.getAuth(), forHTTPHeaderField: "Authorization")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

    let task = URLSession.shared.dataTask(with: request as URLRequest) {data, response, err in
        if data != nil {
            if let dictionary = self.parseJSONData(data!) {
                self.parseDictionary(dictionary, typeOfRequest: requestName)
                control(true)
            }else{

                control(false)
            }
        }
    }
    task.resume()
}

And You can call it with:

serverRequestAuth("myStringRequest1", control: {(check)in

        if check  {
            self.serverRequestAuth("myStringRequest2", control: {(check) in

                if check {

                    self.tableView.reloadData()

                }else{

                    print("error Request 2")
                }
            })


        }else {

            print("error request 1")

        }
    })
Rob
  • 2,649
  • 3
  • 27
  • 34
0

I once had a similar problem. To provide a simple solution I wrote this small library:

https://github.com/prine/ROConcurrency

You can group your requests in Tasks and wait for all request to finish and then reload the table.

var taskRequest1 = TaskComplex { (finished) -> () in
    self.serverRequestAuth("/request1", finished)
}

var taskRequest2 = TaskComplex { (finished) -> () in
    self.serverRequestAuth("/request2", finished)
}

var reloadTable = TaskComplex { (finished) -> () in
    DispatchQueue.main.async{
         // 3. reload the table view
         self.tableView.reloadData()
         finished()
    }
}

var barrierComplex = BarrierComplex(tasks: [taskRequest1, taskRequest2], afterTask: reloadTable)
barrierComplex.startTasks()

Your serverRequestAuth method needs to tell when its finished asynchronously, so you need to add the finished callback:

func serverRequestAuth(_ requestName: String, _ finished:(Bool) -> ()) {
    let requestNameEscaped = requestName.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!


    var request = NSMutableURLRequest()
    request = NSMutableURLRequest(url: URL(string: "\(self.view.getServerPath())\(requestNameEscaped)")!, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 5)

    request.httpMethod = "GET"
    request.setValue(self.view.getAuth(), forHTTPHeaderField: "Authorization")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

    let task = URLSession.shared.dataTask(with: request as URLRequest) {data, response, err in
        if data != nil {
            if let dictionary = self.parseJSONData(data!) {
                self.parseDictionary(dictionary, typeOfRequest: requestName)

                // Here you call finished to tell the Barrier that its finished
                finished()
            }
        }
    }
    task.resume()
}
Prine
  • 12,192
  • 8
  • 40
  • 59