2016-05-04 2 views
18

Я работаю над изображением изображения с аскетинга url. Я попытался создать новый поток для загрузки изображения, а затем обновить на main thread.Быстрое изображение асинхронной нагрузки

func asyncLoadImg(product:Product,imageView:UIImageView){ 
    let downloadQueue = dispatch_queue_create("com.myApp.processdownload", nil) 
    dispatch_async(downloadQueue){ 
     let data = NSData(contentsOfURL: NSURL(string: product.productImage)!) 
     var image:UIImage? 
     if data != nil{ 
      image = UIImage(data: data!) 
     } 
     dispatch_async(dispatch_get_main_queue()){ 
      imageView.image = image 
     } 

    } 
} 

Когда я пытался отладить, что, когда речь идет о dispatch_async (downloadQueue), он выскакивает FUNC. Любое предложение? Thx

+0

http://stackoverflow.com/a/27712427/2303865 –

+0

:(не работает, такой же ошибка.Операции в обратной нити никогда не выполняются –

+0

@LeoDabus Не могли бы вы объяснить это более конкретно? Я не могу понять –

ответ

69

Swift 3 Обновленный код:

extension UIImageView { 
    public func imageFromServerURL(urlString: String) { 

     URLSession.shared.dataTask(with: NSURL(string: urlString)! as URL, completionHandler: { (data, response, error) -> Void in 

      if error != nil { 
       print(error) 
       return 
      } 
      DispatchQueue.main.async(execute: {() -> Void in 
       let image = UIImage(data: data!) 
       self.image = image 
      }) 

     }).resume() 
    }} 

Swift 2,2 Код:

extension UIImageView { 
     public func imageFromServerURL(urlString: String) { 

      NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: urlString)!, completionHandler: { (data, response, error) -> Void in 

       if error != nil { 
        print(error) 
        return 
       } 
       dispatch_async(dispatch_get_main_queue(), {() -> Void in 
        let image = UIImage(data: data!) 
        self.image = image 
       }) 

      }).resume() 
     }} 

Теперь везде, где вам требуется только сделать это, чтобы загрузить изображение с сервера URL:

UIImageView.imageFromServerURL («здесь серверный url»).

Простой!

+0

Помогает ли она затем правильно исправить ответ и закрыть вопрос. –

+2

Я думаю, что это должен быть правильный ответ, потому что это более красноречиво. : +1: –

+0

Рад, что он решил вашу проблему –

1

Здесь этот код может вам помочь.

let cacheKey = indexPath.row 
    if(self.imageCache?.objectForKey(cacheKey) != nil){ 
      cell.img.image = self.imageCache?.objectForKey(cacheKey) as? UIImage 
    }else{ 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), { 
      if let url = NSURL(string: imgUrl) { 
        if let data = NSData(contentsOfURL: url) { 
          let image: UIImage = UIImage(data: data)! 
          self.imageCache?.setObject(image, forKey: cacheKey) 
          dispatch_async(dispatch_get_main_queue(), { 
           cell.img.image = image 
          }) 
         } 
        } 
       }) 
      } 

С помощью этого образа будет загружать и кэш без отстающих вид таблицы пролистывать

+0

Удивительное решение! Но если я быстро прокручу, я все еще вижу, как изображения меняются друг от друга, есть ли способ избежать этого или его невозможно? – Adrian

+0

@Adrian Да, вы можете проверить, нет ли изображения или нет, если он равен нулю, вы его загрузите, если нет - нет. –

16

extension Использование в Swift3. Для решения проблемы сети я рекомендую использовать NSCache:

import UIKit 

let imageCache = NSCache<NSString, AnyObject>() 

extension UIImageView { 
    func loadImageUsingCache(withUrl urlString : String) { 
     let url = URL(string: urlString) 
     self.image = nil 

     // check cached image 
     if let cachedImage = imageCache.object(forKey: urlString as NSString) as? UIImage { 
      self.image = cachedImage 
      return 
     } 

     // if not, download image from url 
     URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in 
      if error != nil { 
       print(error!) 
       return 
      } 

      DispatchQueue.main.async { 
       if let image = UIImage(data: data!) { 
        imageCache.setObject(image, forKey: urlString as NSString) 
        self.image = image 
       } 
      } 

     }).resume() 
    } 
} 

Надеется, что это поможет!

+0

Он работает как шарм, спасибо вам большое !!! –

2

Ведя от ответа Shobhakar Тивари, я думаю, что его часто полезно в таких случаях иметь изображение по умолчанию в случае ошибки, а также для целей загрузки, поэтому я обновил его включить по умолчанию дополнительного изображения:

Swift 3

extension UIImageView { 
public func imageFromServerURL(urlString: String, defaultImage : String?) { 
    if let di = defaultImage { 
     self.image = UIImage(named: di) 
    } 

    URLSession.shared.dataTask(with: NSURL(string: urlString)! as URL, completionHandler: { (data, response, error) -> Void in 

     if error != nil { 
      print(error ?? "error") 
      return 
     } 
     DispatchQueue.main.async(execute: {() -> Void in 
      let image = UIImage(data: data!) 
      self.image = image 
     }) 

    }).resume() 
    } 
} 
+2

Не делайте дублированный ответ, вы можете прокомментировать ответ, чтобы разработчик получил выгоду от него –

0

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

class OfferItemCell: UITableViewCell { 
    @IBOutlet weak var itemImageView: UIImageView! 
    @IBOutlet weak var titleLabel: UILabel! 
    var imageUrl: String? 
} 

И добавить расширение:

import Foundation 
import UIKit 

let imageCache = NSCache<AnyObject, AnyObject>() 
let imageDownloadUtil: ImageDownloadUtil = ImageDownloadUtil() 

extension OfferItemCell { 
    func loadImageUsingCacheWithUrl(urlString: String ) { 
     self.itemImageView.image = nil 
     if let cachedImage = imageCache.object(forKey: urlString as AnyObject) as? UIImage { 
      self.itemImageView.image = cachedImage 
      return 
     } 
     DispatchQueue.global(qos: .background).async { 
      imageDownloadUtil.getImage(url: urlString, completion: { 
       image in 
       DispatchQueue.main.async { 
        if self.imageUrl == urlString{ 
         imageCache.setObject(image, forKey: urlString as AnyObject) 
        self.itemImageView.image = image 
        } 
       } 
      }) 
     } 
    } 
} 

Вы также можете улучшить его и извлечь код для более общего класса клеток, т.е. CustomCellWithImage сделать он более многоразовый.

+0

Я получаю ошибки компиляции для ImageDownloadUtil. Я не вижу, как это объявлено, и я не уверен, как сделать свою собственную версию. – iCyberPaul

0

Наиболее распространенный способ in SWIFT 4 для загрузки асинхронного изображений без blink или changing images эффекта используется для пользовательских UIImageView класса как этот:

//MARK: - 'asyncImagesCashArray' is a global varible cashed UIImage 
var asyncImagesCashArray = NSCache<NSString, UIImage>() 

class AyncImageView: UIImageView { 

//MARK: - Variables 
private var currentURL: NSString? 

//MARK: - Public Methods 

func loadAsyncFrom(url: String, placeholder: UIImage?) { 
    let imageURL = url as NSString 
    if let cashedImage = asyncImagesCashArray.object(forKey: imageURL) { 
     image = cashedImage 
     return 
    } 
    image = placeholder 
    currentURL = imageURL 
    guard let requestURL = URL(string: url) else { image = placeholder; return } 
    URLSession.shared.dataTask(with: requestURL) { (data, response, error) in 
     DispatchQueue.main.async { [weak self] in 
      if error == nil { 
       if let imageData = data { 
        if self?.currentURL == imageURL { 
         if let imageToPresent = UIImage(data: imageData) { 
          asyncImagesCashArray.setObject(imageToPresent, forKey: imageURL) 
          self?.image = imageToPresent 
         } else { 
          self?.image = placeholder 
         } 
        } 
       } else { 
        self?.image = placeholder 
       } 
      } else { 
       self?.image = placeholder 
      } 
     } 
    }.resume() 
} 
} 

пример использование этого класс в UITableViewCell ниже:

class CatCell: UITableViewCell { 

//MARK: - Outlets 
@IBOutlet weak var catImageView: AyncImageView! 

//MARK: - Variables 

var urlString: String? { 
    didSet { 
     if let url = urlString { 
      catImageView.loadAsyncFrom(url: url, placeholder: nil) 
     } 
    } 
} 

override func awakeFromNib() { 
    super.awakeFromNib() 
} 
} 
Смежные вопросы