5

enter image description here

What does this mean? I tried this... still, it gives me the same message:

DispatchQueue.main.async {
    if let imageData = try? Data(contentsOf: url) {
        self.image = UIImage(data: imageData)
    }
}
TylerP
  • 9,600
  • 4
  • 39
  • 43
dbukhari_
  • 59
  • 1
  • 2
  • 1
    Short answer: Pretend the method `Data(contentsOf:)` does not exist. It is a SYNCHRONOUS method and will block the thread on which it is run until it completes. Wrapping the code in `DispatchQueue.main.async()` still runs the method on the main thread, and will still block the main thread. You could conceivably run it on a background thread. Instead, you should use a URLSession as in Louis' answer. – Duncan C Sep 25 '22 at 21:39
  • Does this answer your question? [Trouble Downloading Pictures From URL For Tableview Cell](https://stackoverflow.com/questions/73760498/trouble-downloading-pictures-from-url-for-tableview-cell) – workingdog support Ukraine Sep 26 '22 at 00:13

1 Answers1

9

As the message says, this means that the Data(contentsOf:) call will not return until it got the data, which could be slow if the image is large and the network slow. As you called this function from the main thread, the whole app UI would freeze for several seconds in the worst case.

The compiler/runtime is just helping you to avoid this potential pitfall by returning this error message containing clear indications on how to solve the issue : use URLSession.shared.dataTask(with:completionHandler:) instead of Data(contentsOf:).

func setImageFromStringrURL(stringUrl: String) {
  if let url = URL(fromString: stringUrl) {
    URLSession.shared.dataTask(with: url) { (data, response, error) in
      // Error handling...
      guard let imageData = data else { return }

      DispatchQueue.main.async {
        self.image = UIImage(data: imageData)
      }
    }.resume()
  }
}

This method won't block the main thread. Instead, it will schedule the network call to be performed on a background thread and will execute the callback you provided (responsible of updated the UI) once the data is fetched.

As the callback is also executed on the background thread and UI updates must be made on the main thread you still need to explicitly schedule the UI updates to be executed on the main thread with DispatchQueue.main.async.

Louis Lac
  • 5,298
  • 1
  • 21
  • 36
  • 1
    I had to set `let dataTask = URLSession...` and then call `dataTask.resume()` to get it to work in my case. PS `imageData` should be `data` in your answer, but the edit queue is full. – alstr Oct 27 '22 at 15:29
  • I also get the same message in this line: NSData *jsonData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; – Von Ralph Marquez Nov 22 '22 at 02:42