Bartek Spitza
Bartek Spitza

Reputation: 305

Execute GET request synchronously

I have a function that sends a GET request to an API and I need to wait for the response before I can continue with the rest of my code.

I have tried various different threads but haven't got it to work. I've been trying to solve this by myself but I am quite confused by threads and so fourth.

These are my functions:

func checkDomains() {
    let endings = [".com"]
    for ending in endings {
        let domainName = names[randomNameIndx] + ending
        let urlString = "https://domainr.p.mashape.com/v2/status?mashape-key={my-key}" + domainName

        let url = URL(string: urlString)
        var request = URLRequest(url: url!)

        request.setValue("{my-key}", forHTTPHeaderField: "X-Mashape-Key")
        request.setValue("application/json", forHTTPHeaderField: "Accept")
        request.httpMethod = "GET"
        var ourBool = false

        DispatchQueue.main.sync {
            let task = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, er) in

                do {
                    print("hey")
                    if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {
                        ourBool = String(describing: json).contains("inactive")

                        if ourBool {
                            self.domainStatuses.append("available")
                        } else {
                            self.domainStatuses.append("taken")
                        }
                    }
                } catch {

                }


            })
            task.resume()
        }
    }
}

@objc func btnTapped(sender: UIButton) {
        self.prepareForNewName()
        sender.shake(direction: "horizontal", swings: 1)
        self.checkDomains() // This needs to finish before calling the next functions
        self.setupForNewName()
        self.animateForNewName()
}

Upvotes: 1

Views: 2305

Answers (3)

Bartek Spitza
Bartek Spitza

Reputation: 305

Thank you for your answers. I just came home and realized there is a simpler way of doing this.

let task = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in

    do {
            ...
            if response != nil {
                DispatchQueue.main.async {
                    self.setupForNewName()
                    self.animateForNewName()
                }
            }
        }
    } catch {
        print(error)
    }
})
task.resume()

Of course this is dependent on the response of the API but I am confident enough the API will always respond.

Upvotes: 1

MichaelV
MichaelV

Reputation: 1261

Lately it is a good practice to do network call asynchronously. There some technics to make code simpler, like https://cocoapods.org/pods/ResultPromises TBC...

Upvotes: 0

AleX
AleX

Reputation: 167

My suggestion is in adding callback param into your async function. Example below:

func checkDomains(_ onResult: @escaping (Error?) -> Void)

Then you can call onResult inside your function in places where server return success result or error.

func checkDomains(_ onResult: @escaping (Error?) -> Void) {
    ...
    let task = URLSession.shared.dataTask ... {
       do {
           //Parse response
           DispatchQueue.main.async { onResult(nil) }
       } catch {
           DispatchQueue.main.async { onResult(error) }
       }
       ...
    }
}

The last thing you need pass callback param in place where you calling checkDomains function

@objc func btnTapped(sender: UIButton) {
    self.prepareForNewName()
    sender.shake(direction: "horizontal", swings: 1)
    self.checkDomains { [unowned self] error in
        if let error = error {
            // handle error
            return
        }
        self.setupForNewName()
        self.animateForNewName()
    }
}

Upvotes: 1

Related Questions