Loading/Downloading image from URL on Swift Loading/Downloading image from URL on Swift ios ios

Loading/Downloading image from URL on Swift


Xcode 8 or later • Swift 3 or later

Synchronously:

if let filePath = Bundle.main.path(forResource: "imageName", ofType: "jpg"), let image = UIImage(contentsOfFile: filePath) {    imageView.contentMode = .scaleAspectFit    imageView.image = image}

Asynchronously:

Create a method with a completion handler to get the image data from your url

func getData(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {    URLSession.shared.dataTask(with: url, completionHandler: completion).resume()}

Create a method to download the image (start the task)

func downloadImage(from url: URL) {    print("Download Started")    getData(from: url) { data, response, error in        guard let data = data, error == nil else { return }        print(response?.suggestedFilename ?? url.lastPathComponent)        print("Download Finished")        // always update the UI from the main thread        DispatchQueue.main.async() { [weak self] in            self?.imageView.image = UIImage(data: data)        }    }}

Usage:

override func viewDidLoad() {    super.viewDidLoad()    print("Begin of code")    let url = URL(string: "https://cdn.arstechnica.net/wp-content/uploads/2018/06/macOS-Mojave-Dynamic-Wallpaper-transition.jpg")!     downloadImage(from: url)    print("End of code. The image will continue downloading in the background and it will be loaded when it ends.")}

Extension:

extension UIImageView {    func downloaded(from url: URL, contentMode mode: ContentMode = .scaleAspectFit) {        contentMode = mode        URLSession.shared.dataTask(with: url) { data, response, error in            guard                let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,                let mimeType = response?.mimeType, mimeType.hasPrefix("image"),                let data = data, error == nil,                let image = UIImage(data: data)                else { return }            DispatchQueue.main.async() { [weak self] in                self?.image = image            }        }.resume()    }    func downloaded(from link: String, contentMode mode: ContentMode = .scaleAspectFit) {         guard let url = URL(string: link) else { return }        downloaded(from: url, contentMode: mode)    }}

Usage:

imageView.downloaded(from: "https://cdn.arstechnica.net/wp-content/uploads/2018/06/macOS-Mojave-Dynamic-Wallpaper-transition.jpg")


(Swift 4 update)To answer the original question directly, here's the swift equivalent of the posted Objective-C snippet.

let url = URL(string: image.url)let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catchimageView.image = UIImage(data: data!)

DISCLAIMER:

It's important to note that the Data(contentsOf:) method will download the contents of the url synchronously in the same thread the code is being executed, so do not invoke this in the main thread of your application.

An easy way to make the same code run asynchronously, not blocking the UI, is by using GCD:

let url = URL(string: image.url)DispatchQueue.global().async {    let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch    DispatchQueue.main.async {        imageView.image = UIImage(data: data!)    }}

That said, in real life applications, if you want to have the best User Experience and avoid multiple downloads of the same image, you may want to also have them not only downloaded, but cached. There's already quite a few libraries that does that very seamless and they are all really easy to use. I personally recommend Kingfisher:

import Kingfisherlet url = URL(string: "url_of_your_image")// this downloads the image asynchronously if it's not cached yetimageView.kf.setImage(with: url) 

And that's it


If you just want to load image (Asynchronously!) - just add this small extension to your swift code:

extension UIImageView {    public func imageFromUrl(urlString: String) {        if let url = NSURL(string: urlString) {            let request = NSURLRequest(URL: url)            NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {                (response: NSURLResponse?, data: NSData?, error: NSError?) -> Void in                if let imageData = data as NSData? {                    self.image = UIImage(data: imageData)                }            }        }    }}

And use it this way:

myImageView.imageFromUrl("https://robohash.org/123.png")