Подтвердить что ты не робот

Swift 3: отображение изображения с URL-адреса

В Swift 3 я пытаюсь захватить изображение из Интернета и имею следующие строки кода:

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)

Что я здесь делаю неправильно?

4b9b3361

Ответ 1

В своём коде есть несколько вещей:

  • Вы используете много кастингов, которые не нужны.
  • Вы обрабатываете свой URL как локальный URL-адрес файла, что не так.
  • Вы никогда не загружаете URL-адрес, который будет использоваться вашим изображением.

Первое, что мы собираемся сделать, это объявить вашу переменную как let, поскольку мы не будем ее модифицировать позже.

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.

Затем нам нужно загрузить содержимое этого URL-адреса. Мы можем сделать это с помощью объекта URLSession. Когда вызывается обработчик завершения, у нас будет UIImage, загруженный из Интернета.

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

Наконец, вам нужно вызвать resume в задаче загрузки, иначе ваша задача никогда не запустится:

downloadPicTask.resume().

Весь этот код может выглядеть немного пугающим, но API-интерфейсы URLSession основаны на блоках, поэтому они могут работать асинхронно. Если вы заблокируете поток пользовательского интерфейса в течение нескольких секунд, ОС убьет ваше приложение.

Ваш полный код должен выглядеть следующим образом:

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

Ответ 2

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

Ответ 3

Вы также можете использовать Alamofire\AlmofireImage для этой задачи: https://github.com/Alamofire/AlamofireImage

Код должен выглядеть примерно так (на основе первого примера по ссылке выше):

import AlamofireImage

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

В то время как он аккуратный, но безопасный, вы должны подумать, стоит ли это накладные расходы Pod. Если вы собираетесь использовать больше изображений и хотите добавить фильтр и переходы, я бы подумал об использовании AlamofireImage

Ответ 4

Использование Alamofire разработано для меня на Swift 3:

Шаг 1:

Интеграция с использованием контейнеров.

pod 'Alamofire', '~ > 4.4'

pod 'AlamofireImage', '~ > 3.3'

Шаг 2:

import AlamofireImage

import Alamofire

Шаг 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
}
}

Ответ 5

Самый простой способ по мне будет использовать SDWebImage

Добавьте это в свой файл подкачки

  pod 'SDWebImage', '~> 4.0'

Запустить программу установки

Теперь импортируйте SDWebImage

      import SDWebImage

Теперь для установки изображения с URL-адреса

    imageView.sd_setImage(with: URL(string: "http://www.domain/path/to/image.jpg"), placeholderImage: UIImage(named: "placeholder.png"))

Он отобразит изображение заполнителя, но когда будет загружено изображение, оно отобразит изображение с URL-адреса. Ваше приложение никогда не выйдет из строя.

Это основная особенность SDWebImage

Категории UIImageView, UIButton, MKAnnotationView, добавляющие веб-образ и управление кешем

Асинхронный загрузчик изображений

Асинхронная память + кэширование образа диска с автоматической обработкой кэша

Декомпрессия фонового изображения

Гарантируйте, что один и тот же URL-адрес не будет загружен несколько раз

Гарантируйте, что фиктивные URL-адреса не будут повторяться снова и снова

Гарантирует, что основной поток никогда не будет заблокирован  Представления!

Используйте GCD и ARC

Чтобы узнать больше https://github.com/rs/SDWebImage

Ответ 6

Используйте это расширение и загружайте изображение быстрее.

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

Ответ 7

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

Ответ 8

Swift

Хорошее решение для расширения собственной функциональности с помощью расширений

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

Использование

Инициализатор удобства не работает и принимает необязательный URL - подход безопасен.

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