Cargando / Descargar image de la URL en Swift

Me gustaría cargar una image desde una URL en mi aplicación, así que primero intenté con Objective-C y funcionó, sin embargo, con Swift, tengo un error de compilation:

'imageWithData' no está disponible: use la construcción de objects 'UIImage (datos :)'

Mi funcion:

@IBOutlet var imageView : UIImageView override func viewDidLoad() { super.viewDidLoad() var url:NSURL = NSURL.URLWithString("http://myURL/ios8.png") var data:NSData = NSData.dataWithContentsOfURL(url, options: nil, error: nil) imageView.image = UIImage.imageWithData(data)// Error here } 

En Objective-C:

 - (void)viewDidLoad { [super viewDidLoad]; NSURL *url = [NSURL URLWithString:(@"http://myURL/ios8.png")]; NSData *data = [NSData dataWithContentsOfURL:url]; _imageView.image = [UIImage imageWithData: data]; _labelURL.text = @"http://www.quentinroussat.fr/assets/img/iOS%20icon's%20Style/ios8.png"; } 

¿Alguien puede explicarme por qué imageWithData: no funciona con Swift y cómo puedo resolver el problema.

Xcode 8 • Swift 3

Sincrónicamente:

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

Asíncronamente:

Cree un método con un manejador de finalización para get los datos de image de su url

 func getDataFromUrl(url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) { URLSession.shanetworking.dataTask(with: url) { data, response, error in completion(data, response, error) }.resume() } 

Cree un método para download la image (inicie la tarea)

 func downloadImage(url: URL) { print("Download Started") getDataFromUrl(url: url) { data, response, error in guard let data = data, error == nil else { return } print(response?.suggestedFilename ?? url.lastPathComponent) print("Download Finished") DispatchQueue.main.async() { self.imageView.image = UIImage(data: data) } } } 

Uso:

 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. print("Begin of code") if let url = URL(string: "http://www.apple.com/euro/ios/ios8/a/generichttp://iosberry.comog.png") { imageView.contentMode = .scaleAspectFit downloadImage(url: url) } print("End of code. The image will continue downloading in the background and it will be loaded when it ends.") } 

Extensión :

  extension UIImageView { func downloadedFrom(url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) { contentMode = mode URLSession.shanetworking.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() { self.image = image } }.resume() } func downloadedFrom(link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) { guard let url = URL(string: link) else { return } downloadedFrom(url: url, contentMode: mode) } } 

Uso:

 imageView.downloadedFrom(link: "http://www.apple.com/euro/ios/ios8/a/generichttp://iosberry.comog.png") 

(Actualización Swift 3) Swift cambió un poco desde las primeras respuestas. La forma más simple:

 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-catch imageView.image = UIImage(data: data!) 

EDITAR :

Si desea hacer que el código funcione asynchronous, puede lograrlo fácilmente con 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!) } } 

Si solo desea cargar la image (¡Asíncrona!) , Solo agregue esta pequeña extensión a su código rápido:

 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) } } } } } 

Y utilícelo de esta manera:

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

Swift 2.2 || Xcode 7.3

¡Obtuve increíbles resultados ! con la biblioteca rápida AlamofireImage

Proporciona múltiples características como:

  • Descargar asincrónicamente
  • Caché de imágenes de purga automática si ocurren advertencias de memory para la aplicación
  • Caché de URL de image
  • Caché de imágenes
  • Evite descargas duplicadas

y muy fácil de implementar para tu aplicación

Paso 1 Instalar pods


Alamofire 3.3.x

pod 'Alamofire'

AlamofireImage 2.4.x

pod 'AlamofireImage'

Paso.2 Importar y Usar

 import Alamofire import AlamofireImage let downloadURL = NSURL(string: "http://cdn.sstatic.net/Sites/stackoverflow/company/Img/photos/big/6.jpg?v=f4b7c5fee820")! imageView.af_setImageWithURL(downloadURL) 

¡¡Eso es!! cuidará de todo


Muchas gracias a los chicos de Alamofire , por hacer que la vida de iDevelopers sea fácil;)

Xcode 8Swift 3

¡La respuesta de Leo Dabus es increíble! Solo quería proporcionar una solución de funciones todo en uno:

 let url = URL(string: "http://www.apple.com/euro/ios/ios8/a/generichttp://iosberry.comog.png") let task = URLSession.shanetworking.dataTask(with: url!) { data, response, error in guard let data = data, error == nil else { return } DispatchQueue.main.sync() { self.imageView.image = UIImage(data: data) } } task.resume() 

Envolví el código de las mejores respuestas a la pregunta en una sola class reutilizable que amplía UIImageView, de modo que puedes usar UIImageViews de carga asíncrona directamente en tu storyboard (o crearlos desde un código).

Aquí está mi class:

 import Foundation import UIKit class UIImageViewAsync :UIImageView { override init() { super.init(frame: CGRect()) } override init(frame:CGRect) { super.init(frame:frame) } requinetworking init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } func getDataFromUrl(url:String, completion: ((data: NSData?) -> Void)) { NSURLSession.shanetworkingSession().dataTaskWithURL(NSURL(string: url)!) { (data, response, error) in completion(data: NSData(data: data)) }.resume() } func downloadImage(url:String){ getDataFromUrl(url) { data in dispatch_async(dispatch_get_main_queue()) { self.contentMode = UIViewContentMode.ScaleAspectFill self.image = UIImage(data: data!) } } } } 

y aquí es cómo usarlo:

 imageView.downloadImage("http://www.image-server.com/myImage.jpg") 

FYI: para swift-2.0 Xcode7.0 beta2

 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 self.image = UIImage(data: data!) } } } } 
 let url = NSURL.URLWithString("http://live-wallpaper.net/iphone/img/app/i/p/iphone-4s-wallpapers-mobile-backgrounds-dark_2466f886de3472ef1fa968033f1da3e1_raw_1087fae1932cec8837695934b7eb1250_raw.jpg"); var err: NSError? var imageData :NSData = NSData.dataWithContentsOfURL(url,options: NSDataReadingOptions.DataReadingMappedIfSafe, error: &err) var bgImage = UIImage(data:imageData) 

Querrás hacer:

 UIImage(data: data) 

En Swift, han reemplazado la mayoría de los methods de fábrica de Objective C con constructores habituales.

Ver:

https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html#//apple_ref/doc/uid/TP40014216-CH4-XID_26

Swift 2 con error Handle y encabezado de request personalizado

Simplemente agregue la extensión a UIImageView:

 extension UIImageView { public func imageFromUrl(urlString: String) { if let url = NSURL(string: urlString) { let request = NSMutableURLRequest(URL: url) request.setValue("<YOUR_HEADER_VALUE>", forHTTPHeaderField: "<YOUR_HEADER_KEY>") NSURLSession.shanetworkingSession().dataTaskWithRequest(request) { (data, response, error) in guard let data = data where error == nil else{ NSLog("Image download error: \(error)") return } if let httpResponse = response as? NSHTTPURLResponse{ if httpResponse.statusCode > 400 { let errorMsg = NSString(data: data, encoding: NSUTF8StringEncoding) NSLog("Image download error, statusCode: \(httpResponse.statusCode), error: \(errorMsg!)") return } } dispatch_async(dispatch_get_main_queue(), { NSLog("Image download success") self.image = UIImage(data: data) }) }.resume() } } } 

Y luego, usa la nueva imageFromUrl(urlString: String) para download la image

Uso:

 imageView.imageFromUrl("https://i.imgur.com/ONaprQV.png") 

Swift 2.0:

1}

 if let url = NSURL(string: "http://etc...") { if let data = NSData(contentsOfURL: url) { imageURL.image = UIImage(data: data) } } 

O

 imageURL.image = NSURL(string: "http:// image name...") .flatMap { NSData(contentsOfURL: $0) } .flatMap { UIImage(data: $0) } 

2) Agregue este método a VC o Extensión.

 func load_image(urlString:String) { let imgURL: NSURL = NSURL(string: urlString)! let request: NSURLRequest = NSURLRequest(URL: imgURL) NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) { (response: NSURLResponse?, data: NSData?, error: NSError?) in if error == nil { self.image_element.image = UIImage(data: data) } } } 

Uso:

 self.load_image(" url strig here") 

Swift 3

Este método downloadá una image de un website de forma asíncrona y lo almacenará en caching:

  func getImageFromWeb(_ urlString: String, closure: @escaping (UIImage?) -> ()) { guard let url = URL(string: urlString) else { return closure(nil) } let task = URLSession(configuration: .default).dataTask(with: url) { (data, response, error) in guard error == nil else { print("error: \(String(describing: error))") return closure(nil) } guard response != nil else { print("no response") return closure(nil) } guard data != nil else { print("no data") return closure(nil) } DispatchQueue.main.async { closure(UIImage(data: data!)) } }; task.resume() } 

En uso:

  getImageFromWeb("http://www.apple.com/euro/ios/ios8/a/generichttp://iosberry.comog.png") { (image) in if let image = image { let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 200, height: 200)) imageView.image = image self.view.addSubview(imageView) } // if you use an Else statement, it will be in background } 

Un método para get la image que sea segura y funcione con Swift 2.0 y X-Code 7.1:

 static func imageForImageURLString(imageURLString: String, completion: (image: UIImage?, success: Bool) -> Void) { guard let url = NSURL(string: imageURLString), let data = NSData(contentsOfURL: url), let image = UIImage(data: data) else { completion(image: nil, success: false); return } completion(image: image, success: true) } 

Entonces llamarías a este método de la siguiente manera:

 imageForImageURLString(imageString) { (image, success) -> Void in if success { guard let image = image else { return } // Error handling here // You now have the image. } else { // Error handling here. } } 

Si está actualizando la vista con la image, deberá usarla después del "if success {":

  dispatch_async(dispatch_get_main_queue()) { () -> Void in guard let image = image else { return } // Error handling here // You now have the image. Use the image to update the view or anything UI related here // Reload the view, so the image appears } 

La razón por la que esta última parte es necesaria si está utilizando la image en la interfaz de usuario es porque las llamadas de networking llevan time. Si intenta actualizar la interfaz de usuario utilizando la image sin llamar a dispatch_async como se indicó anteriormente, la computadora searchá la image mientras la image todavía se está buscando, encontrará que no hay ninguna image (todavía) y se moverá como si no hubiera ninguna image encontró. Poner su código dentro de un cierre de finalización dispatch_async le dice a la computadora: "Ve, obtén esta image y cuando hayas terminado, completa este código". De esa forma, tendrá la image cuando se llame al código y las cosas funcionarán bien.

Si está buscando una implementación muy simple. (Esto funcionó para mí en Swift 2)

  let imageURL = NSURL(string: "https://farm2.staticflickr.com/1591/26078338233_d1466b7da2_m.jpg") let imagedData = NSData(contentsOfURL: imageURL!)! imageView?.image = UIImage(data: imagedData) 

Implementé dentro de una vista de tabla con una celda personalizada que solo tiene una image

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{ let cell = tableView.dequeueReusableCellWithIdentifier("theCell", forIndexPath: indexPath) as! customTableViewCell let imageURL = NSURL(string: "https://farm2.staticflickr.com/1591/26078338233_d1466b7da2_m.jpg") let imagedData = NSData(contentsOfURL: imageURL!)! cell.imageView?.image = UIImage(data: imagedData) return cell } 

¡Lo único que falta es un!

 let url = NSURL.URLWithString("http://live-wallpaper.net/iphone/img/app/i/p/iphone-4s-wallpapers-mobile-backgrounds-dark_2466f886de3472ef1fa968033f1da3e1_raw_1087fae1932cec8837695934b7eb1250_raw.jpg"); var err: NSError? var imageData :NSData = NSData.dataWithContentsOfURL(url!,options: NSDataReadingOptions.DataReadingMappedIfSafe, error: &err) var bgImage = UIImage(data:imageData!) 

Swift 3 con event handling errores

 let url = URL(string: arr[indexPath.row] as! String) if url != nil { 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 { if data != nil { cell.imgView.image = UIImage(data:data!) }else{ cell.imgView.image = UIImage(named: "default.png") } } } } 

Use este código en Swift

 imageView.image=UIImage(data: NSData(contentsOfURL: NSURL(string: "http://myURL/ios8.png")!)! 

Swift 2.x responde que descarga la image en un file (en contraposition a la respuesta de Leo Dabus, que almacena la image en la memory). Basado en la respuesta de Leo Dabus y la respuesta de Rob de Obtener los datos de NSURLSession DownloadTaskWithRequest desde el manejador de finalización :

  // Set download vars let downloadURL = NSURL() // URL to download from let localFilename = "foobar.png" // Filename for storing locally // Create download request let task = NSURLSession.shanetworkingSession().downloadTaskWithURL(downloadURL) { location, response, error in guard location != nil && error == nil else { print("Error downloading message: \(error)") return } // If here, no errors so save message to permanent location let fileManager = NSFileManager.defaultManager() do { let documents = try fileManager.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false) let fileURL = documents.URLByAppendingPathComponent(localFilename) try fileManager.moveItemAtURL(location!, toURL: fileURL) self.doFileDownloaded(fileURL, localFilename: localFilename) print("Downloaded message @ \(localFilename)") } catch { print("Error downloading message: \(error)") } } // Start download print("Starting download @ \(downloadURL)") task.resume() // Helper function called after file successfully downloaded private func doFileDownloaded(fileURL: NSURL, localFilename: String) { // Do stuff with downloaded image } 

Para Swift-3 y superiores:

 extension UIImageView { public func imageFromUrl(urlString: String) { if let url = URL(string: urlString) { let request = URLRequest(url: url) NSURLConnection.sendAsynchronousRequest(request as URLRequest, queue: .main, completionHandler: { (response, data, error) in if let imageData = data as NSData? { self.image = UIImage(data: imageData as Data) } }) } } }