Swift 3:URL Image使UITableView滚动缓慢问题

我有一个在UIImageView上打印图像URL的扩展。 但我认为问题是我的tableView因为这个扩展而太慢了。 我想我需要为它打开线程。 如何在此扩展中创建一个线程,或者您是否知道另一个解决此问题的解决方案?

我的代码:

 extension UIImageView{ func setImageFromURl(stringImageUrl url: String){ if let url = NSURL(string: url) { if let data = NSData(contentsOf: url as URL) { self.image = UIImage(data: data as Data) } } } } 

我认为,这里的问题是,您需要在table view缓存图像以实现平滑滚动。 每次程序调用cellForRowAt indexPath它都会再次下载图像。 这需要时间。

对于缓存图像,您可以使用SDWebImage , Kingfisher等库。

翠鸟用法示例:

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "identifier", for: indexPath) as! CustomCell cell.yourImageView.kf.setImage(with: URL) // next time, when you will use image with this URL, it will be taken from cache. //... other code } 

希望能帮助到你

可以按照此处的建议使用框架,但您也可以考虑本文所述的“滚动自己的”扩展

你需要做的“全部”是:

  1. 使用URLSession下载您的图像,这是在后台线程上完成的,所以没有口吃和慢滚动。
  2. 完成后,更新主线程上的图像视图。

拿一个

第一次尝试可能看起来像这样:

 func loadImage(fromURL urlString: String, toImageView imageView: UIImageView) { guard let url = URL(string: urlString) else { return } //Fetch image URLSession.shared.dataTask(with: url) { (data, response, error) in //Did we get some data back? if let data = data { //Yes we did, update the imageview then let image = UIImage(data: data) DispatchQueue.main.async { imageView.image = image } } }.resume() //remember this one or nothing will happen :) } 

你可以这样调用这个方法:

 loadImage(fromURL: "yourUrlToAnImageHere", toImageView: yourImageView) 

起色

如果你想要它,你可以添加一个UIActivityIndicatorView来向用户显示“正在加载的东西”,如下所示:

 func loadImage(fromURL urlString: String, toImageView imageView: UIImageView) { guard let url = URL(string: urlString) else { return } //Add activity view let activityView = UIActivityIndicatorView(activityIndicatorStyle: .gray) imageView.addSubview(activityView) activityView.frame = imageView.bounds activityView.translatesAutoresizingMaskIntoConstraints = false activityView.centerXAnchor.constraint(equalTo: imageView.centerXAnchor).isActive = true activityView.centerYAnchor.constraint(equalTo: imageView.centerYAnchor).isActive = true activityView.startAnimating() //Fetch image URLSession.shared.dataTask(with: url) { (data, response, error) in //Done, remove the activityView no matter what DispatchQueue.main.async { activityView.stopAnimating() activityView.removeFromSuperview() } //Did we get some data back? if let data = data { //Yes we did, update the imageview then let image = UIImage(data: data) DispatchQueue.main.async { imageView.image = image } } }.resume() //remember this one or nothing will happen :) } 

延期

本文中提到的另一个改进可能是将其移动到UIImageView上的extension ,如下所示:

 extension UIImageView { func loadImage(fromURL urlString: String) { guard let url = URL(string: urlString) else { return } let activityView = UIActivityIndicatorView(activityIndicatorStyle: .gray) self.addSubview(activityView) activityView.frame = self.bounds activityView.translatesAutoresizingMaskIntoConstraints = false activityView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true activityView.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true activityView.startAnimating() URLSession.shared.dataTask(with: url) { (data, response, error) in DispatchQueue.main.async { activityView.stopAnimating() activityView.removeFromSuperview() } if let data = data { let image = UIImage(data: data) DispatchQueue.main.async { self.image = image } } }.resume() } } 

基本上它与以前的代码相同,但对imageView引用已更改为self

你可以像这样使用它:

 yourImageView.loadImage(fromURL: "yourUrlStringHere") 

当然……包括SDWebImage或Kingfisher作为依赖项更快,并且“大部分时间都可以正常工作”,此外它还可以为您提供其他好处,例如缓存图像等等。 但我希望这个例子表明,为图像编写自己的扩展并不是那么糟糕……再加上你知道在不工作时应该责怪谁;)

希望对你有所帮助。

你的tableview很慢,因为你在主线程的当前线程中加载数据。 您应该加载其他线程的数据,然后在主线程中设置图像(因为所有UI作业必须在主线程中完成)。 您不需要使用第三方库,只需更改您的扩展程序:

 extension UIImageView{ func setImageFromURl(stringImageUrl url: String){ if let url = NSURL(string: url) { DispatchQueue.global(qos: .default).async{ if let data = NSData(contentsOf: url as URL) { DispatchQueue.main.async { self.image = UIImage(data: data as Data) } } } } } } 

对于在后台缓存图像和滚动更快,请使用SDWebImage

  imageView.sd_setImage(with: URL(string: "http://sofzh.miximages.com/ios/image.jpg"), placeholderImage: UIImage(named: "placeholder.png")) 

https://github.com/rs/SDWebImage