我想从我的应用程序中的URL加载图像,所以我首先尝试了Objective-C和它的工作,但是,与Swift,我有一个编译错误:

'imageWithData'不可用:使用对象构造'UIImage(data:)'

我的函数:

@IBOutlet var imageView : UIImageView

override func viewDidLoad() {
    super.viewDidLoad()

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

    imageView.image = UIImage.imageWithData(data)// Error here
}

在objective - c中:

- (void)viewDidLoad {
    [super viewDidLoad];

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

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

有人能解释一下为什么imageWithData:不能与Swift一起工作,我该如何解决这个问题。


当前回答

class Downloader {
    
    class func downloadImageWithURL(url: String) -> UIImage! {
        
        let date = NSData(contentsOf: URL(string: url)!)
        return UIImage(data: date! as Data)
    }
}

用法:

let img = Downloader.downloadImageWithURL(url: imageURL)
        self.imageView1.image = img

其他回答

我建议使用Kingfisher库来异步下载图像。使用翠鸟最好的部分是,它默认缓存所有下载的图像,图像url作为id。下次当您请求下载具有特定URl的图像时,它将从缓存中加载它。

用法:

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

使用Ascyimageview,你可以很容易地加载imageurl在imageview。

let image1Url:URL = URL(string: “(imageurl)” as String)! imageview.imageURL=image1Url

(Swift 4更新) 为了直接回答最初的问题,下面是发布的Objective-C代码片段的快速等效版本。

let url = URL(string: image.url)
let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
imageView.image = UIImage(data: data!)

免责声明:

需要注意的是,Data(contentsOf:)方法将在执行代码的同一线程中同步下载url的内容,因此不要在应用程序的主线程中调用此方法。

让相同的代码异步运行,而不阻塞UI的简单方法是使用GCD:

let url = URL(string: image.url)

DispatchQueue.global().async {
    let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
    DispatchQueue.main.async {
        imageView.image = UIImage(data: data!)
    }
}

也就是说,在现实生活中的应用程序中,如果您希望获得最佳的用户体验并避免同一映像的多次下载,您可能还希望不仅下载它们,而且缓存它们。已经有相当多的库可以无缝地做到这一点,而且它们都非常易于使用。我个人推荐翠鸟:

import Kingfisher

let url = URL(string: "url_of_your_image")
// this downloads the image asynchronously if it's not cached yet
imageView.kf.setImage(with: url) 

就是这样

Swift 4:一个简单的小图像加载器(例如:缩略图),使用NSCache,总是运行在主线程上:

class ImageLoader {

  private static let cache = NSCache<NSString, NSData>()

  class func image(for url: URL, completionHandler: @escaping(_ image: UIImage?) -> ()) {

    DispatchQueue.global(qos: DispatchQoS.QoSClass.background).async {

      if let data = self.cache.object(forKey: url.absoluteString as NSString) {
        DispatchQueue.main.async { completionHandler(UIImage(data: data as Data)) }
        return
      }

      guard let data = NSData(contentsOf: url) else {
        DispatchQueue.main.async { completionHandler(nil) }
        return
      }

      self.cache.setObject(data, forKey: url.absoluteString as NSString)
      DispatchQueue.main.async { completionHandler(UIImage(data: data as Data)) }
    }
  }

}

用法:

ImageLoader.image(for: imageURL) { image in
  self.imageView.image = image
}

为了在UITableView或UICollectionView中获得更好的性能,使用轻量级库智能惰性加载,如果你想从url异步加载图像,可以使用这种惰性加载方法

因此,在这个项目中,我们可以通过使用操作和操作队列并发优化应用程序的性能,在任何视图(UICollectionView或UITableView)中下载多个图像。以下是这个项目的重点智能延迟加载:创建图像下载服务。根据单元格的可见性优先下载。

ImageDownloadService类将创建一个单例实例,并有一个NSCache实例来缓存已下载的图像。我们已经将Operation类继承给TOperation,以便根据我们的需要修改功能。我认为就功能而言,operation子类的属性非常清楚。我们使用KVO监测操作状态的变化。