【发布时间】:2017-04-29 23:56:46
【问题描述】:
我基本上和这个问题有同样的问题:
Slow scroll on UITableView images
我的 UITableView 包含一个大小为 87x123 的 UIImageView。
当我的UITableViewController 被加载时,它首先调用一个循环遍历图像数组的函数。这些图像是从照片库中存储的高分辨率图像。在每次迭代中,它检索图像并将每个图像的大小调整为 87x123,然后将其存储回数组中的原始图像。
当所有图像都调整大小并存储后,它会调用self.tableView.reloadData 将数组中的数据填充到单元格中。
但是,就像提到的问题一样,如果我在所有图像都调整大小并存储在数组中之前快速滚动,我的UITablView 会不稳定并且滞后。
这是有问题的代码:
extension UIImage
{
func resizeImage(originalImage: UIImage, scaledTo size: CGSize) -> UIImage
{
// Avoid redundant drawing
if originalImage.size.equalTo(size)
{
return originalImage
}
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
originalImage.draw(in: CGRect(x: CGFloat(0.0), y: CGFloat(0.0), width: CGFloat(size.width), height: CGFloat(size.height)))
let image = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return image
}
}
func loadImages()
{
DispatchQueue.global(qos: .background).async {
for index in 0..<self.myArray.count
{
if let image = self.myArray[index].image
{
self.myArray[index].image = image.resizeImage(originalImage: image, scaledTo: CGSize(width: 87, height: 123) )
}
if index == self.myArray.count - 1
{
print("FINISHED RESIZING ALL IMAGES")
}
}
}
tableView.reloadData()
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
...
// Size is 87x123
let thumbnailImage = cell.viewWithTag(1) as! UIImageView
DispatchQueue.main.async{
thumbnailImage.image = self.myArray[indexPath.row]
}
thumbnailImage.contentMode = UIViewContentMode.scaleAspectFill
thumbnailImage.layer.borderColor = UIColor.black.cgColor
thumbnailImage.layer.borderWidth = 1.0
thumbnailImage.clipsToBounds = true
return cell
}
我知道在后台线程中执行任何非 UI 操作,这就是我所做的。然后我在cellForRowAt 中所做的就是使用其indexPath.row 将图像加载到单元格中。
问题是,如前所述,如果我开始滚动 UITableView BEFORE FINISHED RESIZING ALL IMAGES 打印出来,即在所有图像调整大小之前,会出现明显的滞后和缓慢.
但是,如果我等到所有图像都已调整大小并在滚动 UITableView 之前调用 FINISHED RESIZING ALL IMAGES,则滚动很顺畅,没有任何延迟。
我可以放置一个加载指示器,让用户等到所有图像都已调整大小并加载到单元格中,然后再进行用户交互,但这会很烦人,因为调整所有高分辨率图像的大小大约需要 8 秒(18 张图片可调整大小)。
有没有更好的方法可以解决这个延迟问题?
更新:在@iWheelBuy 的第二个示例之后,我实现了以下内容:
final class ResizeOperation: Operation {
private(set) var image: UIImage
let index: Int
let size: CGSize
init(image: UIImage, index: Int, size: CGSize) {
self.image = image
self.index = index
self.size = size
super.init()
}
override func main() {
image = image.resizeImage(originalImage: image, scaledTo: size)
}
}
class MyTableViewController: UITableViewController
{
...
lazy var resizeQueue: OperationQueue = self.getQueue()
var myArray: [Information] = []
internal struct Information
{
var title: String?
var image: UIImage?
init()
{
}
}
override func viewDidLoad()
{
....
loadImages()
...
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
...
// Size is 87x123
let thumbnailImage = cell.viewWithTag(1) as! UIImageView
DispatchQueue.main.async{
thumbnailImage.image = self.myArray[indexPath.row].image
}
thumbnailImage.contentMode = UIViewContentMode.scaleAspectFill
return cell
}
func loadImages()
{
let size = CGSize(width: 87, height: 123)
for item in myArray
{
let operations = self.myArray.enumerated().map({ ResizeOperation(image: item.image!, index: $0.offset, size: size) })
operations.forEach { [weak queue = resizeQueue, weak controller = self] (operation) in
operation.completionBlock = { [operation] in
DispatchQueue.main.async { [image = operation.image, index = operation.index] in
self.update(image: image, index: index)
}
}
queue?.addOperation(operation)
}
}
}
func update(image: UIImage, index: Int)
{
myArray[index].image = image
tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: UITableViewRowAnimation.fade)
}
}
但是,在调用 tableView.reloadRows 时,我收到了一个错误提示:
尝试从第 0 节中删除第 0 行,但只有 0 节 更新前
我对它的含义以及如何解决它有点困惑。
【问题讨论】:
标签: ios swift uitableview