swift3 - mercadolibre - Swift 3: muestra la imagen desde la URL
acer swift 3 review (8)
En Swift 3, intento capturar una imagen de internet y tener estas líneas de código:
var catPictureURL = NSURL(fileURLWithPath: "http://i.imgur.com/w5rkSIj.jpg")
var catPictureData = NSData(contentsOf: catPictureURL as URL) // nil
var catPicture = UIImage(data: catPictureData as! Data)
¿Qué estoy haciendo mal aquí?
Rápido
Buena solución para extender la funcionalidad nativa por extensiones
import Foundation
import UIKit
extension UIImage {
convenience init?(url: URL?) {
guard let url = url else { return nil }
do {
let data = try Data(contentsOf: url)
self.init(data: data)
} catch {
print("Cannot load image from url: /(url) with error: /(error)")
return nil
}
}
}
Uso
El inicializador de conveniencia no está disponible y acepta una URL
opcional: el enfoque es seguro.
imageView.image = UIImage(url: URL(string: "some_url.png"))
Hay algunas cosas con su código tal como está:
- Estás utilizando mucho casting, que no es necesario.
- Está tratando su URL como una URL de archivo local, que no es el caso.
- Nunca está descargando la URL para ser utilizada por su imagen.
Lo primero que vamos a hacer es declarar su variable como let
, ya que no vamos a modificarla más tarde.
let catPictureURL = URL(string: "http://i.imgur.com/w5rkSIj.jpg")! // We can force unwrap because we are 100% certain the constructor will not return nil in this case.
Entonces tenemos que descargar los contenidos de esa URL. Podemos hacer esto con el objeto URLSession
. Cuando se llame al controlador de finalización, tendremos un UIImage
descargado de la web.
// Creating a session object with the default configuration.
// You can read more about it here https://developer.apple.com/reference/foundation/urlsessionconfiguration
let session = URLSession(configuration: .default)
// Define a download task. The download task will download the contents of the URL as a Data object and then you can do what you wish with that data.
let downloadPicTask = session.dataTask(with: catPictureURL) { (data, response, error) in
// The download has finished.
if let e = error {
print("Error downloading cat picture: /(e)")
} else {
// No errors found.
// It would be weird if we didn''t have a response, so check for that too.
if let res = response as? HTTPURLResponse {
print("Downloaded cat picture with response code /(res.statusCode)")
if let imageData = data {
// Finally convert that Data into an image and do what you wish with it.
let image = UIImage(data: imageData)
// Do something with your image.
} else {
print("Couldn''t get image: Image is nil")
}
} else {
print("Couldn''t get response code for some reason")
}
}
}
Finalmente, debe llamar al resume
en la tarea de descarga; de lo contrario, su tarea nunca comenzará:
downloadPicTask.resume()
.
Todo este código puede parecer un poco intimidante al principio, pero las API de URLSession
están basadas en bloques para que puedan funcionar de forma asíncrona: si bloquea el subproceso de la interfaz de usuario por unos segundos, el sistema operativo matará su aplicación.
Su código completo debería verse así:
let catPictureURL = URL(string: "http://i.imgur.com/w5rkSIj.jpg")!
// Creating a session object with the default configuration.
// You can read more about it here https://developer.apple.com/reference/foundation/urlsessionconfiguration
let session = URLSession(configuration: .default)
// Define a download task. The download task will download the contents of the URL as a Data object and then you can do what you wish with that data.
let downloadPicTask = session.dataTask(with: catPictureURL) { (data, response, error) in
// The download has finished.
if let e = error {
print("Error downloading cat picture: /(e)")
} else {
// No errors found.
// It would be weird if we didn''t have a response, so check for that too.
if let res = response as? HTTPURLResponse {
print("Downloaded cat picture with response code /(res.statusCode)")
if let imageData = data {
// Finally convert that Data into an image and do what you wish with it.
let image = UIImage(data: imageData)
// Do something with your image.
} else {
print("Couldn''t get image: Image is nil")
}
} else {
print("Couldn''t get response code for some reason")
}
}
}
downloadPicTask.resume()
La forma más fácil para mí será usar SDWebImage
Agregue esto a su archivo de pod
pod ''SDWebImage'', ''~> 4.0''
Ejecutar pod instalar
Ahora importa SDWebImage
import SDWebImage
Ahora para configurar la imagen desde la URL
imageView.sd_setImage(with: URL(string: "http://www.domain/path/to/image.jpg"), placeholderImage: UIImage(named: "placeholder.png"))
Mostrará la imagen del marcador de posición, pero cuando se descargue la imagen mostrará la imagen de la URL. Tu aplicación nunca se bloqueará
Esta es la característica principal de SDWebImage
Categorías para UIImageView, UIButton, MKAnnotationVer agregar imagen web y administración de caché
Un descargador de imágenes asincrónico
Una memoria asíncrona + memoria de caché de imágenes con manejo automático de caducidad de caché
Una descompresión de imagen de fondo
Una garantía de que la misma URL no se descargará varias veces
Una garantía de que las URL falsas no se volverán a intentar una y otra vez
Una garantía de que el hilo principal nunca será bloqueado ¡Actuaciones!
Use GCD y ARC
Para saber más https://github.com/rs/SDWebImage
También podría usar Alamofire / AlmofireImage para esa tarea: https://github.com/Alamofire/AlamofireImage
El código debe ser similar (basado en el primer ejemplo en el enlace de arriba):
import AlamofireImage
Alamofire.request("http://i.imgur.com/w5rkSIj.jpg").responseImage { response in
if let catPicture = response.result.value {
print("image downloaded: /(image)")
}
}
Si bien es ordenado pero seguro, debes considerar si vale la pena la sobrecarga del Pod. Si vas a usar más imágenes y me gustaría agregar también filtros y transiciones, consideraría usar AlamofireImage
Usando Alamofire funcionó para mí en Swift 3:
Paso 1:
Integrar usando pods.
pod ''Alamofire'', ''~> 4.4''
pod ''AlamofireImage'', ''~> 3.3''
Paso 2:
importar AlamofireImage
importar Alamofire
Paso 3:
Alamofire.request("https://httpbin.org/image/png").responseImage { response in
if let image = response.result.value {
print("image downloaded: /(image)")
self.myImageview.image = image
}
}
Use esta extensión y descargue la imagen más rápido.
extension UIImageView {
public func imageFromURL(urlString: String) {
let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
activityIndicator.frame = CGRect.init(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height)
activityIndicator.startAnimating()
if self.image == nil{
self.addSubview(activityIndicator)
}
URLSession.shared.dataTask(with: NSURL(string: urlString)! as URL, completionHandler: { (data, response, error) -> Void in
if error != nil {
print(error ?? "No Error")
return
}
DispatchQueue.main.async(execute: { () -> Void in
let image = UIImage(data: data!)
activityIndicator.removeFromSuperview()
self.image = image
})
}).resume()
}
}
let url = ("https://firebasestorage.googleapis.com/v0/b/qualityaudit-678a4.appspot.com/o/profile_images%2FBFA28EDD-9E15-4CC3-9AF8-496B91E74A11.png?alt=media&token=b4518b07-2147-48e5-93fb-3de2b768412d")
self.myactivityindecator.startAnimating()
let urlString = url
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url)
{
(data, response, error) in
if error != nil {
print("Failed fetching image:", error!)
return
}
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
print("error")
return
}
DispatchQueue.main.async {
let image = UIImage(data: data!)
let myimageview = UIImageView(image: image)
print(myimageview)
self.imgdata.image = myimageview.image
self.myactivityindecator.stopanimating()
}
}.resume()
let url = URL(string: "http://i.imgur.com/w5rkSIj.jpg")
let data = try? Data(contentsOf: url)
if let imageData = data {
let image = UIImage(data: imageData)
}