adimona
adimona

Reputation: 109

Converting Array of URLs into Array of UIImage

I have an array of URLs linking to image files, how do I store them into an array of UIImages?

var imagesArray = [UIImage]()

let links = ["http://example.com/image1.jpg","http://example.com/image2.jpg"] as [String]

There must be an easy solution. If it was one image I could do something like the following:

let url = URL(string: link2image!)!
let imageData = try? Data(contentsOf: url)
let image = UIImage(data: imageData!)!
self.image.append(image)

Upvotes: 4

Views: 2231

Answers (3)

Hitesh Takhtani
Hitesh Takhtani

Reputation: 11

 for img in links {
        if let data = try? Data(contentsOf: URL(string: img)!) {
            let image = UIImage(data: data)
            imageArray.append(image!)
        }
    }

Upvotes: 0

pluto
pluto

Reputation: 546

Maybe you can try Functional programming use: map closure ...

links.map({
    if let imageData = try? Data(contentsOf: URL(string: $0)!) {
        UIImage(data: imageData)
    }
})

But you must know if your links is wrong, it will crash. So, I suggest you make some guard to prevent these crashes. like this...

guard let url = URL(string: $0) else { return nil }

Upvotes: 0

David Pasztor
David Pasztor

Reputation: 54726

The easiest solution would be to just iterate through the array and download the images synchronously using Data(contentsOf:), however, this would be quite insufficient due to synchronous execution.

let images = links.flatMap{ link->UIImage? in
    guard let url = URL(string: link) else {return nil}
    guard let imageData = try? Data(contentsOf: url) else {return nil}
    return UIImage(data: imageData)
}

A better solution would be to download the images asynchronously in parallel, I have written a UIImage extension for this using PromiseKit:

extension UIImage {
    class func downloadedAsync(fromUrl url: URL)->Promise<UIImage> {
        return Promise{ fulfill, reject in
            URLSession.shared.dataTask(with: url, completionHandler: { data, response, error in
                guard let data = data, error == nil else {
                    reject(error!); return
                }
                guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
                    reject(NSError(domain: "Wrong HTTP response code when downloading image asynchronously",code: (response as? HTTPURLResponse)?.statusCode ?? 1000));return
                }
                guard let mimeType = response?.mimeType, mimeType.hasPrefix("image"), let image = UIImage(data: data) else {
                    reject(NSError(domain: "No image in response", code: 700)); return
                }
                fulfill(image)
            }).resume()
        }
    }
}

You call it for an array of links like this:

var imageDownloadTasks = links.flatMap{ link in
    guard let url = URL(string: link) else {return nil}
    return UIImage.downloadedAsync(fromUrl: url)
}

Then execute the promises:

when(fulfilled: imageDownloadTasks).then{ images in
    //use the images, images is of type [UIImage]
}

Upvotes: 3

Related Questions