Swift 3:从URL显示图像

时间:2016-10-02 03:11:35

标签: swift3

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

我在这里做错了什么?

10 个答案:

答案 0 :(得分:47)

您的代码有一些原因:

  1. 你正在使用大量的铸造,这是不需要的。
  2. 您将URL视为本地文件URL,但实际情况并非如此。
  3. 您永远不会下载图片使用的网址。
  4. 我们要做的第一件事就是将您的变量声明为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对象执行此操作。调用完成处理程序后,我们将从Web下载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()

    所有这些代码起初可能看起来有点令人生畏,但URLSession API是基于块的,因此它们可以异步工作 - 如果你阻止你的UI线程几秒钟,操作系统将终止你的应用程序。 / p>

    您的完整代码应如下所示:

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

答案 1 :(得分:28)

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

答案 2 :(得分:8)

使用此扩展程序并更快地下载图片。

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

答案 3 :(得分:7)

您还可以使用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)")
    }
}

虽然它很安全但你应该考虑是否值得开销。 如果您打算使用更多图像并想添加过滤器和转换,我会考虑使用AlamofireImage

答案 4 :(得分:5)

夫特

通过扩展

扩展原生功能的良好解决方案
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"))

答案 5 :(得分:4)

Swift 3:

上使用Alamofire为我服务

第1步:

使用pod进行整合。

pod' Alamofire','〜> 4.4'

pod' AlamofireImage','〜> 3.3'

第2步:

导入AlamofireImage

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

答案 6 :(得分:2)

根据我的最简单方法是使用SDWebImage

将其添加到您的pod文件

  pod 'SDWebImage', '~> 4.0'

运行pod install

现在导入SDWebImage

      import SDWebImage

现在从网址设置图片

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

它将显示占位符图像,但是当下载图像时,它将显示来自网址的图像。您的应用程序永远不会崩溃

这是SDWebImage的主要功能

UIImageView,UIButton,MKAnnotationView的类别添加Web图像和缓存管理

异步图片下载

具有自动缓存到期处理的异步内存+磁盘映像缓存

背景图片解压缩

保证不会多次下载相同的网址

保证不会一次又一次地重试虚假网址

保证主线程永远不会被阻止  表演!

使用GCD和ARC

了解更多https://github.com/rs/SDWebImage

答案 7 :(得分:1)

使用UIImageView扩展名加载URL图像。

let imageCache = NSCache<NSString, UIImage>()

extension UIImageView {

    func imageURLLoad(url: URL) {

        DispatchQueue.global().async { [weak self] in
            func setImage(image:UIImage?) {
                DispatchQueue.main.async {
                    self?.image = image
                }
            }
            let urlToString = url.absoluteString as NSString
            if let cachedImage = imageCache.object(forKey: urlToString) {
                setImage(image: cachedImage)
            } else if let data = try? Data(contentsOf: url), let image = UIImage(data: data) {
                DispatchQueue.main.async {
                    imageCache.setObject(image, forKey: urlToString)
                    setImage(image: image)
                }
            }else {
                setImage(image: nil)
            }
        }
    }
}

答案 8 :(得分:0)

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

答案 9 :(得分:0)

我使用 AlamofireImage 它适用于 Loading urlImageView 中,它也有 Placeholder 选项.

func setImage (){

  let image = “https : //i.imgur.com/w5rkSIj.jpg”
  if let url = URL (string: image)
  {
    //Placeholder Image which was in your Local(Assets)
    let image = UIImage (named: “PlacehoderImageName”)
    imageViewName.af_setImage (withURL: url, placeholderImage: image)
  }

}

注意:- 不要忘记在 Pod 文件和导入语句中添加 AlamofireImage

举个例子,

pod 'AlamofireImage' 在你的 PodFile 和 ViewController import AlamofireImage