使用UIImage

时间:2019-08-15 03:58:30

标签: ios swift uitableview

已加载UIImage,并且滚动经过1个单元格后,它会滞后并继续用于其他人。

是因为单元可重复使用吗? enter image description here

extension TableViewController: UITableViewDelegate, UITableViewDataSource {

        func numberOfSections(in tableView: UITableView) -> Int {
            return 1
        }

        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return post.count
        }

        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = UITableViewCell(style: .default, reuseIdentifier: "myCell")
            DispatchQueue.main.async {

                //MARK:- UIImage as URL
                let postImage = self.post[indexPath.row]
                if let photoUrl = URL(string: postImage.photoUrl!)
                {
                    do {
                        let data = try Data(contentsOf: photoUrl)
                        cell.imageView?.image = UIImage (data: data)
                        cell.imageView?.frame = CGRect(x: 0, y: 0, width: 450, height: 450)

                    } catch {
                        print("")
                    }
                }// postImage
            }
            return cell
        }

    } //MARK:- Extension into Table View Controller

1 个答案:

答案 0 :(得分:0)

它滞后是因为您在主线程上执行“大量”操作。 DispatchQueue.main.async在这里没有帮助,因为它仍在主线程中执行代码。您实际上只需要在主线程上执行以下两行代码:

cell.imageView?.image = UIImage (data: data)
cell.imageView?.frame = CGRect(x: 0, y: 0, width: 450, height: 450)

实际上,您甚至不需要第二个,因为布局应由单元格本身完成(例如,可以通过约束或自动调整大小的蒙版进行设置)

您的代码中最重的操作是let data = try Data(contentsOf: photoUrl),因为它从网络执行数据加载。因此,您的主要目标是在主线程之外执行此操作。例如,您可以这样做:

DispatchQueue.global().async {
    do {
        let data = try Data(contentsOf: photoUrl)
        let image = UIImage(data: data) // this also could be pretty much heavy if the image is big so since we're already in background let's do it here
        DispatchQueue.main.async {
            imageView.image = UIImage (data: data)
        }
    }
    catch {
        print("")
    }
}

该示例非常基本,仍然存在未解决的问题。例如,如果将图像设置为imageView时要比缩放图像大很多,那也可能会很昂贵,因此最好在后台线程中将图像缩放为imageView大小。此外,单元格是可重用的,因此当加载一个图像时,该单元格可能已用于显示另一幅图像,因此您还需要一种处理它的方法。另外,您可能需要缓存加载的图像,以避免每次滚动时从网络上重新加载它们。

因此,这里有很多工作要做,为了简化起见,我建议您使用Kingfisher之类的库(仅作为示例,不要广告)