521 Stimmen

Laden/Herunterladen von Bildern von URL auf Swift

Ich möchte ein Bild aus einer URL in meiner Anwendung laden, also habe ich es zuerst mit Objective-C versucht und es hat funktioniert, aber mit Swift habe ich einen Kompilierungsfehler:

'imageWithData' ist nicht verfügbar: Verwenden Sie die Objektkonstruktion 'UIImage(data:)'

Meine Funktion:

@IBOutlet var imageView : UIImageView

override func viewDidLoad() {
    super.viewDidLoad()

    var url:NSURL = NSURL.URLWithString("http://meineURL/ios8.png")
    var data:NSData = NSData.dataWithContentsOfURL(url, options: nil, error: nil)

    imageView.image = UIImage.imageWithData(data)// Fehler hier
}

In Objective-C:

- (void)viewDidLoad {
    [super viewDidLoad];

    NSURL *url = [NSURL URLWithString:(@"http://meineURL/ios8.png")];
    NSData *data = [NSData dataWithContentsOfURL:url];

    _imageView.image = [UIImage imageWithData: data];
    _labelURL.text = @"http://www.urltest.fr/assets/img/iOS%20icon's%20Style/ios8.png";
 }

Kann mir bitte jemand erklären, warum imageWithData: nicht mit Swift funktioniert und wie ich das Problem lösen kann.

3voto

Raj Salla Punkte 75

Ich empfehle die Verwendung der Kingfisher-Bibliothek zum herunterladen von Bildern asynchron. Der beste Teil beim Verwenden von Kingfisher ist, dass es standardmäßig alle heruntergeladenen Bilder zwischenspeichert, mit der Bild-URL als ID. Das nächste Mal, wenn Sie anfordern, das Bild mit dieser bestimmten URL herunterzuladen, wird es aus dem Cache geladen.

Verwendung:

newsImage.kf.setImage(with: imageUrl!, placeholder: nil, options: nil, progressBlock: nil, completionHandler: { (image, error, cacheType, imageUrl) in
                if error == nil{
                    self.activityIndicator.stopAnimating()
                }else if error != nil{
                    self.activityIndicator.stopAnimating()
                }
            })

3voto

iamVishal16 Punkte 1642

Bearbeitet für letzte Änderung 09/2021

// Es ist besser, die Erweiterung zu verwenden
extension UIImageView {
func downloadImage(from URLString: String, with completion: @escaping (_ response: (status: Bool, image: UIImage? ) ) -> Void) {
    guard let url = URL(string: URLString) else {
        completion((status: false, image: nil))
        return
    }

    URLSession.shared.dataTask(with: url) { data, response, error in
        guard error == nil else {
            completion((status: false, image: nil))
            return
        }

        guard let httpURLResponse = response as? HTTPURLResponse,
              httpURLResponse.statusCode == 200,
              let data = data else {
            completion((status: false, image: nil))
            return
        }

        let image = UIImage(data: data)
        completion((status: true, image: image))
    }.resume()
}
}

Fröhliches Coden. Prost:)

3voto

Ben Patch Punkte 1185

Ein Methode, um das Bild sicher zu bekommen und mit Swift 2.0 und X-Code 7.1 zu arbeiten:

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

Dann würden Sie diese Methode so aufrufen:

imageForImageURLString(imageString) { (image, success) -> Void in
        if success {
            guard let image = image 
                 else { return } // Fehlerbehandlung hier 
            // Sie haben jetzt das Bild.
         } else {
            // Fehlerbehandlung hier.
        }
    }

Wenn Sie die Ansicht mit dem Bild aktualisieren, müssen Sie dies nach dem "if success {" verwenden:

    dispatch_async(dispatch_get_main_queue()) { () -> Void in
         guard let image = image 
              else { return } // Fehlerbehandlung hier 
         // Sie haben jetzt das Bild. Verwenden Sie das Bild, um die Ansicht oder alles andere in der Benutzeroberfläche zu aktualisieren
         // Aktualisieren Sie die Ansicht, damit das Bild erscheint
    }

Der Grund, warum dieser letzte Teil benötigt wird, wenn Sie das Bild in der Benutzeroberfläche verwenden, liegt daran, dass Netzwerkanfragen Zeit in Anspruch nehmen. Wenn Sie versuchen, die Benutzeroberfläche mit dem Bild zu aktualisieren, ohne wie oben dispatch_async aufzurufen, wird der Computer nach dem Bild suchen, während das Bild noch geladen wird, feststellen, dass kein Bild vorhanden ist (noch) und weitermachen, als ob kein Bild gefunden wurde. Wenn Sie Ihren Code innerhalb einer dispatch_async-Vervollständigungsschleife platzieren, sagen Sie dem Computer: "Gehe, hol dieses Bild und wenn du fertig bist, dann vervollständige diesen Code." Auf diese Weise haben Sie das Bild, wenn der Code aufgerufen wird, und die Dinge funktionieren gut.

2voto

Mojtaba Hosseini Punkte 68078

Von Swift 5.5 an ist es so einfach wie das Aufrufen einer Funktion wie:

imageView.setImage(url: myImageURL, placeholder: thePlaceholder)

die native Swift concurrency in dieser einfachen Erweiterung verwendet:

extension UIImageView {
    func setImage(url: URL, placeholder: UIImage?) {
        self.image = placeholder

        Task { [weak self] in
            let (data, _) = try await URLSession.shared.data(from: url)
            self?.image = UIImage(data: data)
        }
    }
}

Beachten Sie, dass das placeholder verwendet wird, bis das Bild aus dem Netzwerk ankommt.

Außerdem haben wir die Task in die Funktion eingebettet, damit die Funktion selbst synchron aufgerufen werden kann.

2voto

Crashalot Punkte 31926

Swift 2.x Antwort, die ein Bild in eine Datei herunterlädt (im Gegensatz zu Leo Dabus Antwort, die das Bild im Speicher speichert). Basierend auf Leo Dabus Antwort und Robs Antwort von Die Daten von NSURLSession DownloadTaskWithRequest aus dem Abschluss-Handler abrufen:

    // Setze Download-Variablen
    let downloadURL = NSURL() // URL zum Herunterladen
    let localFilename = "foobar.png" // Dateiname zum lokalen Speichern

    // Erstelle Download-Anfrage
    let task = NSURLSession.sharedSession().downloadTaskWithURL(downloadURL) { location, response, error in
        guard location != nil && error == nil else {
            print("Fehler beim Herunterladen der Nachricht: \(error)")
            return
        }

        // Wenn hier, keine Fehler, also Nachricht an permanenten Speicherort speichern
        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("Nachricht heruntergeladen @ \(localFilename)")
        } catch {
            print("Fehler beim Herunterladen der Nachricht: \(error)")
        }
    }

    // Download starten
    print("Download starten @ \(downloadURL)")
    task.resume()

// Hilfsfunktion, die nach erfolgreichem Download der Datei aufgerufen wird
private func doFileDownloaded(fileURL: NSURL, localFilename: String) {

    // Verarbeiten des heruntergeladenen Bildes

}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X