I’d suggest not using try?
(which discards any meaningful error data) and instead use try
wrapped in a do
-catch
block, and in the catch
block, examine what the error is. Right now, you’re flying blind.
Or, better, use URLSession.shared.dataTask(with:)
and look at the error
in the completion handler.
You asked:
... but why is this such a bad thing [to use Data(contentsOf:)
] if it is the background thread?
Yes, by dispatching this to a global queue you’ve mitigated the “don’t block the main thread” problem. But Data(contentsOf:)
doesn’t provide much diagnostic information about why it failed. Also, it ties up one of the very limited number of worker threads that GCD draws upon. If you exhaust the worker thread pool, then GCD won’t be able to do anything else until it’s freed up. Using URLSession
offers the chance to do more meaningful diagnostics and avoids blocking GCD worker threads.
So, I would suggest removing all of those !
forced unwrapped operators and not using Data(contentsOf:)
. Thus, I might suggest something like:
guard
let path = movie.poster_path,
let baseURL = URL(string: "http://image.tmdb.org/t/p/w185")
else {
print("problem getting path/URL")
return
}
let url = baseURL.appendingPathComponent(path)
URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
guard
let data = data,
let response = response as? HTTPURLResponse,
error == nil
else {
print("network error:", error ?? "Unknown error")
return
}
guard 200..<300 ~= response.statusCode else {
print("invalid status code, expected 2xx, received", response.statusCode)
}
guard let image = UIImage(data: data) else {
print("Not valid image")
return
}
DispatchQueue.main.async {
self?.movieImage.image = image
}
}.resume()
Then, by displaying the error, if any, we’ll see what the problem was. FWIW, the above network request identifies three types of errors, which might be helpful for diagnostic purposes:
- Basic network errors
- HTTP errors
- Content errors (not an image)