adamprocter
adamprocter

Reputation: 856

Swift 3 URL Session - add time out against URL

The following code is working great but I need to add a timeout if data connection is too slow.

  func preload(){

        let url = URL(string: "https://example.com/loadteams.php")
        let data = try? Data(contentsOf: url!)

        if data == nil{
                 showAlert()

            }else{
        values = try! JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! [[String : AnyObject]]

        }

       }

I assume I need to bring URLSession into this but I am not sure how to do so, I understand it should be something along the lines.

 let urlconfig = URLSessionConfiguration.default
        urlconfig.timeoutIntervalForRequest = 5
        urlconfig.timeoutIntervalForResource = 5
        self.session = URLSession(configuration: urlconfig, delegate: self.delegates, delegateQueue: nil)  

This has error no delegates

Upvotes: 1

Views: 4670

Answers (1)

Rob
Rob

Reputation: 438307

You can call dataTask(with:):

let session: URLSession = {
    let configuration = URLSessionConfiguration.default
    configuration.timeoutIntervalForRequest = 5
    configuration.timeoutIntervalForResource = 5
    return URLSession(configuration: configuration, delegate: nil, delegateQueue: nil)
}()

func preload(completionHandler: @escaping ([[String: AnyObject]]?) -> Void) {
    let url = URL(string: "https://example.com/loadteams.php")!

    let task = session.dataTask(with: url) { data, response, error in
        if let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []), let array = json as? [[String: AnyObject]] {
            DispatchQueue.main.async {
                completionHandler(array)
            }
        } else {
            DispatchQueue.main.async {
                completionHandler(nil)
            }
        }
    }
    task.resume()
}

You may have noticed, though, that unlike your rendition, this is asynchronous. So you probably should apply a completion handler pattern, so you know when it's done. So, I'd personally do the UI update from the caller, e.g.:

preload() { values in
    guard let values = values else {
        self.showAlert()
        return
    }

    self.values = values
    // trigger whatever UI update you want here
}

Upvotes: 3

Related Questions