从 NSData 转换到 UIImage 很慢,阻塞 UITableView

Posted

技术标签:

【中文标题】从 NSData 转换到 UIImage 很慢,阻塞 UITableView【英文标题】:Transform from NSData to UIImage very slow, block UITableView 【发布时间】:2017-09-23 00:07:01 【问题描述】:

我从Core Data 获得NSData,当我从NSData 转换为UIImage 时,它使我的UITableView 滚动非常缓慢。在将图像存储到Core Data 之前,我已经调整了图像的大小。有没有好的方法来做到这一点。一开始想用Kingfisher,但是好像没有这种方法可以实现。

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cellIdentifier = "ListTableViewCell"

    guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? ListTableViewCell  else 
        fatalError("The dequeued cell is not an instance of MealTableViewCell.")
    
    //cell.imageContentPhoto.kf.setImage(with: url)
    cell.imageContentPhoto.image = UIImage(data: photos[indexPath.row] as Data)//photo is NSData, I got it from Core Data

return cell

【问题讨论】:

【参考方案1】:

您的问题不在于转换速度很慢,而是在您滚动时它已经完成了很多次。

为了优化 UITable,ios 不会为 n 行创建 n 个单元格。它创建 x+2 个单元格 (IIRC),其中 x 是 可见 单元格的数量。

当 cellForRowAt 被调用时,你调用 dequeueReusableCell,它获取一个空闲单元并将其分配给行。这样,当您滚动时,不会发生对象初始化,并减慢滚动速度。

您的代码的问题(现在很明显)是在将单元格分配给行之后,您再次转换图像并对其进行初始化。

您应该提前初始化图像数组,例如在 viewDidLoad 中。那么您的代码将如下所示:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
   let cellIdentifier = "ListTableViewCell"

   guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? ListTableViewCell  else 
       fatalError("The dequeued cell is not an instance of MealTableViewCell.")
   
   //cell.imageContentPhoto.kf.setImage(with: url)
   cell.imageContentPhoto.image = imagesArray[indexPath.row] // or something similar

  return cell

当然,如果您有很多不同的图像,那么进行某种延迟加载可能是值得的。滚动时保留占位符图像,当它停止时,仅加载相关图像。这当然要复杂得多,留给学生作为练习。

【讨论】:

非常感谢。你解决了我的问题。现在我将做这些复杂的事情,放置一个持有人图像,并仅加载相关图像。这对我来说有点困难。我会检查更多相关材料。谢谢~

以上是关于从 NSData 转换到 UIImage 很慢,阻塞 UITableView的主要内容,如果未能解决你的问题,请参考以下文章

直接从 AFNetworking 获取 NSData,而不是让它转换为 UIImage

将UIImage转换为NSData并在Swift中转换回UIImage?

将 UIImage 转换为 NSData 并在 Swift 中转换回 UIImage?

将UIImage转换为NSData并返回UIImage

NSData/UIImage 到字符串

如何将 UIImage 转换为 NSData 或 CFDataRef?