Michel
Michel

Reputation: 11763

session.dataTask synchronization issue

I have some trouble with the code below. Though it works, there is some timing problem.

First let me say what I expect, I suppose the completion handler should be run when the data download is complete and my image ready to use. But reality seems to be quite different. When I try it the completion handler is called right away (I can see 'All OK' in the console) as if everything was instantaneous. But the image gets actually displayed much later. What am I missing?

let imageURL = URL(string: myURLString)
session = URLSession.shared,
_ = session.dataTask(with: imageURL) {[weak self]
    (data: Data?, response: URLResponse?, error: Error?) in
    if error == nil {
        print("All OK")
        self?.theImage = UIImage(data: data!)
        self?.theView.image = self?.theImage
    } else {print(error!)}

    DispatchQueue.main.async {
        self?.activityIndicator.stopAnimating()
        self?.theView.setNeedsDisplay()
    }
    }.resume()

Upvotes: 0

Views: 290

Answers (1)

Umar Farooque
Umar Farooque

Reputation: 2059

Can you try this code?

The control should not be actually going inside the handler at first call. And I think there are a few mistakes in your code as well which I pointed out earlier, especially the main thread is required for updating UI.

    let session : URLSession
    let config = URLSessionConfiguration.default
    var resultFromServer: Any?
    let responseResultData = [String:Any]()
    session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
    session.dataTask(with: request) { (data, response, error ) in

        if error != nil {

            DispatchQueue.main.async(execute: {

                session.invalidateAndCancel()

            })

        }else{

            let httpResponse: HTTPURLResponse = response as! HTTPURLResponse

                do{

                    resultFromServer = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers)
                    if httpResponse.statusCode == 200  || httpResponse.statusCode == 201 || httpResponse.statusCode == 202 || httpResponse.statusCode == 204 || httpResponse.statusCode == 203 {

                        if let respArr = resultFromServer as? [Any]{

                          //resp is array


                        }else if let respdict = resultFromServer as? [String : Any] {

                            //resp is dict


                        }else{

                           //resp is something else maybe string, etc

                        }

                    }
                    else {


                       //error status code something like 500, 404, etc

                    }


                }

                catch let error as NSError {

                    DispatchQueue.main.async(execute: {

                        session.invalidateAndCancel()

                    })
                }

            }

        session.finishTasksAndInvalidate()
        }.resume()

Upvotes: 1

Related Questions