2017-07-24 28 views
1

我想顯示一個用戶列表與圖像。下面是代碼Swift 3:tableView複製從Firebase加載的圖像

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! UserListTableViewCell 
    let message = messages[indexPath.row] 
    cell.message = message 
    return cell 
} 

在UserListTableViewCell文件,我下載的圖片(也使用高速緩存),並展示在桌子上了。但是我發現有些行具有重複/重複的圖像。重新加載時,重複項消失,但它重新垂直滾動。

出現這種情況:enter image description here

這裏是UserListTableViewCell文件:

import UIKit 
import Firebase 

class UserListTableViewCell: UITableViewCell { 

@IBOutlet weak var username: UILabel! 
@IBOutlet weak var textMessage: UILabel! 
@IBOutlet weak var timeLabel: UILabel! 
@IBOutlet weak var userImage: UIImageView! 



var message: Message? { 

    didSet { 

     if let id = message?.chatPartnerID() { 

      let database = Database.database().reference() 
      let ref = database.child("Users").child(id) 
      ref.observeSingleEvent(of: .value, with: { 
       (snapshot) in 

       if let dictionary = snapshot.value as? [String: AnyObject] { 


         self.username.text = dictionary["username"] as? String 

         if let profileImageUrl = dictionary["image"] as? String, profileImageUrl != "" { 
                  self.userImage.image = UIImage(named: "blank-user") 
          self.userImage.loadImageFromCacheWithUrlString(urlString: profileImageUrl) 
          self.userImage.layer.cornerRadius = self.userImage.frame.size.width/2 
          self.userImage.clipsToBounds = true 

         } else { 

          self.userImage.image = UIImage(named: "blank-user") 
          self.userImage.layer.cornerRadius = self.userImage.frame.size.width/2 
          self.userImage.clipsToBounds = true 
         } 

       } 



      }, withCancel: nil) 
     } 


     textMessage.text = (message?.text)! + " " + (message?.chatPartnerID())! 

     if let seconds = message?.timestamp?.doubleValue { 
      let timestampDate = Date(timeIntervalSince1970: seconds) 

      let dateFormatter = DateFormatter() 
      dateFormatter.dateFormat = "hh:mm a" 
      timeLabel.text = dateFormatter.string(from: timestampDate) 
     } 


     //userImage.image = message?. 
    } 
} } 

圖片下載擴展文件:

extension UIImageView { 
func loadImageFromCacheWithUrlString(urlString: String) { 

    if urlString != "" { 
     self.image = nil 

     if let cachedImage = imageCache.object(forKey: urlString as AnyObject) { 

      self.image = cachedImage as? UIImage 
      self.contentMode = .scaleAspectFill 
      return 
     } 


     let url = URL(string : urlString) 

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

      if error != nil { 
       print(error!) 
       return 
      } 

      DispatchQueue.main.async(execute: { 

       if let downloadedImage = UIImage(data: data!) { 

        imageCache.setObject(downloadedImage, forKey: urlString as AnyObject) 
        self.image = downloadedImage 
        self.contentMode = .scaleAspectFill 
       } 


      }) 

     }).resume() 
    } 


} 

}

+0

你是怎麼寫的叫在'cell.message'的代碼? – Larme

+0

Reuse cell set nil image view –

+0

在UserListTableViewCell中分享您的圖片查看代碼 –

回答

2

基本上你使用電池重用所以每次新重用先前的單元格,以便重用vious cell data,所以你需要清除以前的數據。你應該爲零圖片查看下載新的圖像或使用圖像佔位符

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! UserListTableViewCell 
    . cell.userImage.image = nil 
     let message = messages[indexPath.row] 
     cell.message = message 
     return cell 
} 

更新: From apple doc

如果一個UITableViewCell對象是可重複使用的,也就是說,它有一個複用標識符,此方法只調用在從UITableView方法返回對象之前dequeueReusableCell(withIdentifier :) 。出於性能考慮,您應該只重置與內容無關的單元格屬性,例如,alpha,編輯和選擇狀態。 tableView(_:cellForRowAt :) 中的表視圖委託應該在重用單元時始終重置所有內容。如果單元對象沒有關聯的重用標識符,則不調用此方法。如果您重寫此方法,則必須確保調用超類實現。

所以把你的UserListTableViewCell

override func prepareForReuse() { 
    super.prepareForReuse() 
     self.userImage.image() = nil 
    // self.userImage.image = nil // above line not working then try this 
} 
+0

已經嘗試過,發生同樣的問題。 – snowwalker

+0

你會想這條線嗎?cell.userImage.image = UIImage(named:「」) –

+0

仍然沒有太幸運 – snowwalker

1

你能不能嘗試通過這種方式

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! UserListTableViewCell 
    cell.userImage.image = UIImage(named: "blank-user") 
    let message = messages[indexPath.row] 
    cell.message = message 
    return cell 
} 
+0

謝謝,但它沒有工作 – snowwalker

2

另一個解決方法

您可以使用UIImage(data: Data(contentsOf: URL(string: urlString)!))來從URL圖像,但佔用主線程,所以緩存是必要的。 此解決方案不會顯示錯誤圖像但不好,因爲初始化原因延遲。

class URLImageRetriever { 
    fileprivate static var cache = NSCache<AnyObject,UIImage>() 
    static func getImage(from urlString: String) -> UIImage? { 
     var image = URLImageRetriever.cache.object(forKey: urlString as AnyObject) 
     if image == nil { 
      do { 
       try image = UIImage(data: Data(contentsOf: URL(string: urlString)!)) 
       if let image = image { 
        Designer.cache.setObject(image, forKey: urlString as AnyObject) 
       } 
      } catch { 

      } 
     } 
     return image 
    } 
} 

產地

您的擴展loadImageFromCacheWithUrlString可能不適合這種情況。

讓我們討論一下這種情況:

  1. 你的ImageView a要求提出的url-a圖像。現在有一個URLSession task-a正在運行。
  2. 您的UITableViewCell被重用以呈現另一個數據源,因此您的ImageView a請求呈現url-b的圖像。現在有一個URLSession task-b正在運行。
  3. task-b檢索圖片url-b。您的ImageView a現在完美地顯示url-b的圖像。
  4. tast-a以後檢查圖片。您的ImageView被設置爲顯示圖像形式url-a。讓我們感到困惑。

每次檢索圖片時,都應該檢查一下你想要用imageview顯示的內容。

例如:

URLImageUtil.loadImageFromCacheWithUrlString(urlString: profileImageUrl, completion: { 
    url, image in 
    if self.message.profileImageUrl == url { 
     self.userImage.image = image 
    } 
}) 
class URLImageUtil { 
    static func loadImageFromCacheWithUrlString(urlString: String, completion: @escaping (_ url: URL,_ image: UIImage)->Void) { 
     if let url = URL(string: urlString) { 
      URLSession.shared.dataTask(
       with: url, completionHandler: {data,response,error in 
        if (data) != nil { 
         if let image = UIImage.init(data: data!) { 
          completion(url, image) 
         } else { 
          print("data not image from url: \(url)") 
         } 
        } else { 
         print("no data from url: \(url)") 
        } 
      }) 
     } else { 
      print("error url: \(urlString)") 
     } 
    } 
} 
+0

我可以讓代碼與.resume()一起運行,但仍然有圖像重複問題。 – snowwalker

+0

您可以嘗試其他解決方案。查看我的更新。 – Codus

+0

感謝您的幫助。我試過了,但速度太慢了。任何其他建議以不同的方式做同樣的事情? – snowwalker

相關問題