36 votes

Swift 3 : Afficher une image à partir d'une URL

Dans Swift 3, j'essaie de capturer une image depuis Internet, et j'ai ces lignes de code :

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'est-ce que je fais de mal ici ?

0 votes

La deuxième ligne renvoie nil.

0 votes

Pourquoi n'utilisez-vous pas directement l'URL dans la première ligne au lieu d'utiliser NSURL pour le couler plus tard ?

0 votes

Je n'ai pas bien vu ce que vous essayiez de faire tout à l'heure. Je vais écrire une réponse appropriée maintenant.

56voto

Andy Ibanez Points 1752

Il y a plusieurs choses avec votre code tel qu'il est :

  1. Vous utilisez beaucoup de moulage, ce qui n'est pas nécessaire.
  2. Vous traitez votre URL comme une URL de fichier local, ce qui n'est pas le cas.
  3. Vous ne téléchargez jamais l'URL qui sera utilisée par votre image.

La première chose que nous allons faire est de déclarer votre variable en tant que let car nous n'avons pas l'intention de le modifier ultérieurement.

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.

Ensuite, nous devons télécharger le contenu de cette URL. Nous pouvons le faire avec la fonction URLSession objet. Lorsque le gestionnaire d'achèvement est appelé, nous aurons un objet UIImage téléchargés sur le 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")
        }
    }
}

Enfin, vous devez appeler resume sur la tâche de téléchargement, sinon votre tâche ne démarrera jamais :

downloadPicTask.resume() .

Tout ce code peut sembler un peu intimidant au premier abord, mais la URLSession Les API sont basées sur des blocs, ce qui leur permet de fonctionner de manière asynchrone. Si vous bloquez votre thread d'interface utilisateur pendant quelques secondes, le système d'exploitation mettra fin à votre application.

Votre code complet devrait ressembler à ceci :

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

7 votes

Mon Dieu, c'est là où j'essayais d'arriver en fin de compte ; votre réponse a dépassé de loin ce que j'attendais. Cela me donne un énorme coup de pouce. Merci beaucoup, beaucoup pour votre aide !

35voto

user7887623 Points 271
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)
}

0 votes

data! <- Ceci se plantera si le téléchargement échoue pour une raison quelconque.

11voto

Sandip Gill Points 654

Utilisez cette extension et téléchargez des images plus rapidement.

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

0 votes

Comment l'utilisez-vous ?

1 votes

@Ahmadreza vous l'utilisez comme ceci : yourImageViewOutlet.imageFromURL(urlString : yourUrl)

9voto

Dudi Levy Points 79

Vous pouvez aussi utiliser Alamofire \AlmofireImage pour cette tâche : https://github.com/Alamofire/AlamofireImage

Le code devrait ressembler à quelque chose comme ça (basé sur le premier exemple sur le lien ci-dessus) :

import AlamofireImage

Alamofire.request("http://i.imgur.com/w5rkSIj.jpg").responseImage { response in
    if let catPicture = response.result.value {
        print("image downloaded: \(image)")
    }
}

Bien qu'il soit soigné et sûr, vous devez vous demander si cela vaut les frais généraux de Pod. Si vous avez l'intention d'utiliser plus d'images et que vous souhaitez ajouter des filtres et des transitions, je vous conseille d'utiliser AlamofireImage.

0 votes

Alors comment enregistrer cette image dans un fichier ?

7voto

dimpiax Points 96

Swift

Bonne solution pour étendre la fonctionnalité native par extensions

import UIKit

extension UIImage {
  convenience init?(url: URL?) {
    guard let url = url else { return nil }

    do {
      self.init(data: try Data(contentsOf: url))
    } catch {
      print("Cannot load image from url: \(url) with error: \(error)")
      return nil
    }
  }
}

Utilisation

L'initialisateur pratique est défaillant et accepte l'optionnel URL - L'approche est sûre.

imageView.image = UIImage(url: URL(string: "some_url.png"))

0 votes

Peut-on l'utiliser en toute sécurité lorsqu'il y a beaucoup de données (par exemple 1000, 2000, etc.) dans le tableau ?

0 votes

@PratyushPratik cette approche n'a rien à voir directement avec la vue de table, donc vous pouvez l'utiliser, mais je ne la recommande pas. Pour le flux de table view, vous devez utiliser les opérations (pour l'annulation) et le prefetching.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X