【问题标题】:UITableView lag when scrolling滚动时 UITableView 滞后
【发布时间】:2020-10-22 22:48:29
【问题描述】:

在我们的应用中,我们从服务器动态填充表格视图。

滚动时表格滞后。

所以我创建了一个调度队列:

    var queue = DispatchQueue(label: "myqueue")

然后在tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 方法中我做了:

    queue.async {
            DispatchQueue.main.async {
                cell.placeIconView.layer.cornerRadius = cell.placeIconView.frame.width / 2
                cell.placeIconView.clipsToBounds = true
            }
            
            let poiImgs = HttpResponseHolder.shared.POIS[indexPath.row].imagesUrls
            
            if poiImgs!.count > 0 {
                let url = URL(string: poiImgs![0])
                
                let data = try? Data(contentsOf: url!)
                DispatchQueue.main.async {
                    cell.placeIconView.image = UIImage(data: data!)
                }
            }
            
            if poiImgs?.count == 0 && HttpResponseHolder.shared.POIS[indexPath.row].detailsOnWeb == false {
                
                DispatchQueue.main.async {
                    cell.placeIconView.image = UIImage(named: "img_poi_placeholder")
                }
            }
            
            if poiImgs?.count == 0 && HttpResponseHolder.shared.POIS[indexPath.row].detailsOnWeb == true {
                
                DispatchQueue.main.async {
                    cell.placeIconView.image = UIImage(named: "url_img_placeholder")
                }
            }
            
            DispatchQueue.main.async {
                cell.dotImgView.isHidden = true
            }
            
            if self.showCrowdingState == true {
                let crowdIndex = HttpResponseHolder.shared.POIS[indexPath.row].crowdingLevel
                
                DispatchQueue.main.async {
                    cell.dotImgView.isHidden = false
                }
                
                switch crowdIndex {
                case 1:
                    // green
                    DispatchQueue.main.async {
                        cell.dotImgView.image = UIImage(named: "greenDot")
                    }
                case 2:
                    // yellow
                    DispatchQueue.main.async {
                        cell.dotImgView.image = UIImage(named: "yellowDot")
                    }
                case 3:
                    // green
                    DispatchQueue.main.async {
                        cell.dotImgView.image = UIImage(named: "redDot")
                    }
                default:
                    break
                }
            } else {
                DispatchQueue.main.async {
                    cell.dotImgView.image = nil
                }
            }
        }

如您所见,我将单元配置放在后台线程中(并在主线程中推回 UI 更新)。

这解决了延迟问题,但是当我滚动表格视图时,加载其内容会延迟。

我是不是搞错了什么?

【问题讨论】:

  • 一些一般性说明:cellForRow 将在主队列上执行。您在其中经常切换队列,这也会影响速度。作为一般方法,您应该让模型在显示单元之前填充可用的单元(并显示加载指示器,直到有足够的模型准备好填充视口),或者您应该允许单元在它们之后异步加载它们自己的模型已经显示。有许多框架和架构或库允许这种方法,例如 RxSwift + MVVM 或 IGListKit。

标签: ios swift xcode uitableview


【解决方案1】:

您可以缓冲 ui 更新任务,最后您可以使用单个 dispatch 语句在主队列上运行。

queue.async {
    typealias Task = () -> Void
    var operations:[Task] = []

    operations.append {
        cell.placeIconView.layer.cornerRadius = cell.placeIconView.frame.width / 2
        cell.placeIconView.clipsToBounds = true
    }
    operations.append {
        cell.placeIconView.image = UIImage(data: data!)
    }
    operations.append {
        ...
    }
    
    DispatchQueue.main.async {
        operations.forEach({ $0() })
        operations.removeAll()
    }
}

【讨论】:

  • 嗨,我在 DispaQueue.main.async 上遇到错误:上下文闭包类型 '@convention(block) () -> Void' 需要 0 个参数,但在闭包主体中使用了 1 个跨度>
  • 好的,现在没有错误,但表格仍在以缓慢的方式加载图像,而且有些滞后。
  • let data = try? Data(contentsOf: url!)这个操作比较耗时
猜你喜欢
  • 2014-11-11
  • 1970-01-01
  • 2015-09-24
  • 1970-01-01
  • 1970-01-01
  • 2017-06-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多