eonr
eonr

Reputation: 29

Wait for multiple Alamofire Requests to finish

I have a below function in my network class which do the Alamofire Request process. I'm calling this function in my model class and when Alamofire finishes the request it calls delegate function which notify model class. My problem is that I'm calling this Alamofire function multiple times and both should finish before notifying model class. Now I handle it with very dummy way. As I searched, DispatchGroup can be used but I can't figure it out, how to implement it. Thank you.

Model Class

 @objc func refresh_fiks(){
    let network = Network()
    network.delegate = self
    self.teams = [[]]
    network.getRequest(req: 1)
    network.getRequest(req: 2)

}

Request Function:

    func response(){
    print(response_json.count)
    if(response_json.count == path){
        self.delegate?.sendJson(response_json)
    }
    }
    func getRequest(req: Int) {
    path = req
    let rot = Router(method: .get, path: req, parameters: nil)
    Alamofire.request(rot)
        .response { response in
            print(response.request?.url! as Any)
            // check for errors
            guard response.error == nil else {
                // got an error in getting the data, need to handle it
                print(response.error!)
                let errorJson: JSON = [ "Error" : "Can't get the data!"]
                self.response_json.append(errorJson)
                self.response()
                return
            }
            // make sure we got some JSON since that's what we expect
            guard (response.data?.base64EncodedString()) != nil else {
                print("Error: \(String(describing: response.error))")
                let errorJson: JSON = [ "Error" : "Can't get the data!"]
                self.response_json.append(errorJson)
                self.response()
                return
            }
            guard response.response?.statusCode == 200 else{
                let errorJson: JSON = [ "Error" : "Can't get the data!"]
                self.response_json.append(errorJson)
                self.response()
                return
            }
            let json = JSON(data: response.data!)
            // get and print the title
            if json != nil{
                self.response_json.append(json)
                self.response()
            } else {
                let errorJson: JSON = [ "Error" : "Can't get the data!"]
                self.response_json.append(errorJson)
                self.response()
                return
            }
    }
}

Upvotes: 1

Views: 3164

Answers (1)

Woof
Woof

Reputation: 1383

I've made few changes in your code:

Network class:

func response(array: [JSON]){
    print(array.count)
    if(array.count == path){
        self.delegate?.sendJson(array)
    }
}

func getMultipleRequests(_ requests: [Int]) {
    DispatchQueue.global(qos: .background).async {
        let group = DispatchGroup()

        var array: [JSON] = []

        for request in requests {

            group.enter()

            self.getRequest(req: request, completion: { (json) in
                array.append(json)
                group.leave()
            })
        }

        group.wait()
        //this line below won't be called until all entries will leave the group
        self.response(array: array)
    }
}

func getRequest(req: Int, completion: @escaping (_ json: JSON) -> Void) {
    path = req
    let rot = Router(method: .get, path: req, parameters: nil)
    Alamofire.request(rot)
        .response { response in
            print(response.request?.url! as Any)
            // check for errors
            guard response.error == nil else {
                // got an error in getting the data, need to handle it
                print(response.error!)
                let errorJson: JSON = [ "Error" : "Can't get the data!"]
                completion(errorJson)
                return
            }
            // make sure we got some JSON since that's what we expect
            guard (response.data?.base64EncodedString()) != nil else {
                print("Error: \(String(describing: response.error))")
                let errorJson: JSON = [ "Error" : "Can't get the data!"]
                completion(errorJson)
                return
            }
            guard response.response?.statusCode == 200 else{
                let errorJson: JSON = [ "Error" : "Can't get the data!"]
                completion(errorJson)
                return
            }
            let json = JSON(data: response.data!)
            // get and print the title
            if json != nil{
                completion(json)
            } else {
                let errorJson: JSON = [ "Error" : "Can't get the data!"]
                completion(errorJson)
                return
            }
    }
}

So the getRequest function now have a completion block that will return a json result off each request and the function getMultipleRequests that will receive a bunch of requests from anyone

This how you can use it

Your class, that calls refresh_fiks:

@objc func refresh_fiks(){
    let network = Network()
    network.delegate = self
    self.teams = [[]]

    network.getMultipleRequests([1,2])
}

Also, instead of using group.wait() you might need to use group.notify, it's better to notify that all entries leaved the group in specified queue, like the main:

group.notify(queue: DispatchQueue.main, execute: {
   print("All Done") 
   self.response(array: array)
}) 

What to read about the DispatchGroups:

RayWenderlich

ALL ABOUT SWIFT

Upvotes: 5

Related Questions