2016-12-19 15 views
0

Firebaseを使用して画像をセルのImageViewにロードしていますが、!問題があります。 reusable cellsがロードされても画像が再ロードされないようにするキャッシュ機構を使用していますが、スクロールしてからTableViewまで画像がロードされません。テーブルビュー画像がスクロールするまでロードされない

ここにコードがあります。

 public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 

    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell 
    cell.imgv.image = nil 

if let urlString = self.filteredFlats[indexPath.row].flatThumbnailImage?.imageDownloadURL 
    { 
     imageURLString = urlString 

     let url = URL(string: urlString) 
     if let imagefromCache = imageCache.object(forKey: urlString as AnyObject) as? UIImage 
     { 
      DispatchQueue.main.async { 
       cell.imgv.image = imagefromCache 
       return 
      } 
     } 
     else 
     { 

      URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in 
       DispatchQueue.main.async { 

        let imagetoCache = UIImage(data:data!) 

        if self.imageURLString == urlString 
        { 
         cell.imgv.image = imagetoCache 

        } 
        self.imageCache.setObject(imagetoCache!, forKey: urlString as AnyObject) 

       } 
      }).resume() 
     } 
    } 
    return cell 
} 

私はURLSessionは、画像をダウンロードしてImageViewにそれを設定する際に問題があると思うが、上下にスクロールするときにロードされたイメージは、バックと呼ばれるindexpath.rowまで表示されません。

私はそれがこのif文であることを認識しました。

if self.imageURLString == urlString 

しかし、私がそれを取り除くと、細胞は再利用可能な細胞の行動を悪化させます。一部のセルでは、古いキャッシュイメージが表示されます。

実際に何が起こっているのか分からない。期待していなかったのは、それ自体が複雑な構造のようなものなのです。TableViews

ありがとうございました。

+0

ImageViewのの拡張を作成このURLを使用して:http://stackoverflow.com/a/37019507/3400991あなたに役立つことを願って –

答えて

0

私は、imageURLStringがあなたのクラスのフィールド(おそらくUIViewController)であると推測しています。 これは、あなたのメソッドに入るたびにimageURLString = urlStringがその値を変更することを意味します。

テーブルがレンダリングされると、必要なイメージがキャッシュにない場合にダウンロードをトリガするたびに、各セルのメソッドが呼び出されます。しかし、これらの呼び出しの後、imageURLStringの値は最後のセルに使用されるURLになります。したがって、このセルだけが実際にロードされたイメージを使用します。

あなたのコードを修正したい場合は、(この場合にはUITableViewCellサブクラスを作成する)セルクラスにフィールドを移動することによって、例えばセル当たり1 imageURLStringを、持っている、とcell.imageURLString

0
によって imageURLStringself.imageURLStringを交換する必要があります

imageCacheはグローバルでなければならず、tableView(_:cellForRowAt :)の内部に配置しないでください。

代わりに、var imageCache = String:UIImageを除くカスタムUIImageViewクラスのすべてをタックします。その世界を離れる。

このCustomImageViewクラスの内部にあるloadImage(urlString:String)関数を使用して、すべてのUIImageViewをCustomImageView!に変更します。

例:

@IBOutlet弱いのvar userImage:UIImageView!

変更

@IBOutlet弱いのvar userImage:CustomImageView!

import UIKit 

// global var 
var imageCache = [String: UIImage]() 

class CustomImageView: UIImageView { 

    var lastURLUsedToLoadImage: String? 

    func loadImage(urlString: String) { 
     lastURLUsedToLoadImage = urlString 

     self.image = nil 

     if let cachedImage = imageCache[urlString] { 
      self.image = cachedImage 
      return 
     } 

     guard let url = URL(string: urlString) else { return } 

     URLSession.shared.dataTask(with: url) { (data, response, err) in 
      if let err = err { 
       print("Failed to fetch post image:", err) 
       return 
      } 

      if url.absoluteString != self.lastURLUsedToLoadImage { 
       return 
      } 

      guard let imageData = data else { return } 

      let photoImage = UIImage(data: imageData) 

      imageCache[url.absoluteString] = photoImage 

      // update the UI 
      DispatchQueue.main.async { 
       self.image = photoImage 
      } 

      }.resume() 
    } 
} 

loadメソッドを呼び出す例:

cell.userImage.loadImage(urlString: userImageUrl) 
0

私は、YouTube上のiOSチュートリアルから学習され、以下の方法でそれを解決します。 CustomImageViewクラスを作成し、画像キャッシュを保存するにはlet imageCache = NSCache<AnyObject, AnyObject>()を作成することができます。テーブルビューをスクロールすると、imageViewのimageCacheがある場合は直接使用します。ただし、exsitがない場合はimage URL文字列を入力して保存します。

import UIKit 

let imageCache = NSCache<AnyObject, AnyObject>() 

class CustomImageView: UIImageView { 

    var imageUrlString :String? 

    func loadImageWithString(_ urlString:String){ 

     imageUrlString = urlString 

     let request = URLRequest(url: URL(string:urlString)!) 

     self.image = nil 

     //imageCache exist,and use it directly 
     if let imageFromCache = imageCache.object(forKey: urlString as AnyObject) as? UIImage { 

      self.image = imageFromCache 
     } 

     //imageCache doesn't exist,then download the image and save it 
     URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in 

      guard let data = data, error == nil else { 
       print(error?.localizedDescription as Any) 
       return 
      } 

      DispatchQueue.main.async() { 

       let imageToCache = UIImage(data: data) 

       imageCache.setObject(imageToCache!, forKey: urlString as String as AnyObject) 

       if self.imageUrlString == urlString{ 

        self.image = imageToCache 
       } 
      } 

     }).resume() 

    } 

} 

、次のようにカスタムセルクラスファイルで、我々はそれを使用することができます。

if let imageUrlString = thumbnailUrlString { 
       thumbnailImageView.loadImageWithString(imageUrlString) 
      } 

注1、thumbnailImageViewこと:CustomImageView 2、thumbnailUrlStringはオプションです

関連する問題