I want to create UIImage(urlString: String?). There is no error when I run this code but it is not working.
extension UIImage {
convenience init?(urlString: String?) {
var imageData = Data()
guard let urlString = urlString else { return nil}
guard let url = URL(string: urlString) else { return nil}
URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
print("Error: \(error.localizedDescription)")
return
}
guard let response = response as? HTTPURLResponse else {
print("Empty image response")
return
}
print("HTTP image response code: \(response.statusCode)")
guard let data = data else {
print("Empty image data")
return
}
imageData = data
}.resume()
self.init(data: imageData)
}
}
CodePudding user response:
UIImage initializer init(data:) is a synchronous method. Your self.init(data: imageData) method is called before the async method dataTask finish its request and execute its completion handler.
What I suggest is to create an instance method extending URL and add a completion handler to it:
extension URL {
func asyncImage(completion: @escaping (UIImage?) -> Void) {
URLSession.shared.dataTask(with: self) { data, _, _ in
guard let data = data, let image = UIImage(data: data) else {
completion(nil)
return
}
completion(image)
}.resume()
}
}
Usage:
yourURL.asyncImage { image in
guard let image = image else { return }
// use image here
}
Another option is to extend UIImageView as shown in this post
