tableView的优化问题

来源:互联网 发布:淘宝中差评多久会消失 编辑:程序博客网 时间:2024/04/25 06:27

tableView的优化问题

-主要体现在: 快速滑动的失帧现象、界面卡顿现象、内存暴涨

在我们进行多数据展示时,以100条数据为例而且cell样式有多种,例如网易新闻,微博,这种以图文混排为主的App中.

优化之处:

  • 1> cell重用

    dequeueReusableCellWithIdentifier:forIndexPath:
    大家都熟悉了就不在多说.通过cellIdentifier唯一标示来进行重用

  • 2> tableView在cell显示之前会频繁调用heightForRowAtIndexPath,用来计算contentSize ,所以我们应该尽量少的调用这个方法.

  • 3> 如果我们做预估算行高的话,那就定义静态的cell,这样系统在自估算行高会不用多次创建cell ,从而达到一个提升系能的作用.

    cell的高度是根据内容变化的时候,只计算一次,将高度缓存起来

verridefunctableView(tableView:UITableView,heightForRowAtIndexPath indexPath:NSIndexPath) ->CGFloat{//获取模型let status =self.statuses![indexPath.row]//判断模型里面之前有没有缓存过行高if status.rowHeight!=nil{//之前保存过行高,直接返回行高return status.rowHeight!}
  • 4> 如果不是特殊需要的话,设置tableCell及其子视图的opaque属性设置为YES(系统默认). 包括背景色,它的alpha值应该设置为1,设置一些颜色及透明度也会有性能的消耗.

  • 5>在添加tableCell时
    如果不是特殊需要,最好不要使用
    tableView.insertRows(at: , with: ),而是直接调用readloadData来进行添加,因为前者会进行cellForRowAt indexPath:的多次调用

  • 6> 减少视图的数量不要过多的添加控件.因为tableCell在进行渲染是会消耗性能.如果我们要实现选中高亮,那就对cell的contentView.Layer层进行操作.

  • 7> 不要阻塞线程
    — cell中的图片开线程异步加载,相信每个人都会想到。线程开过多了会造成资源浪费,内存开销过大。图片过多时可以不要一滚动就走cellForRow方法,可以在scrollview的代理方法中做限制,当滚动开始减速的时候才加载显示在当前屏幕上的cell(通过tableview的dragging和declearating两个状态也能判断

图片处理

  • 1.后台下载图片后再回主线程刷新UI,避免阻塞主线程
  • 2.图片过大回造成GPU负担过大,可以在图片下载后压缩尺寸后显示
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {      var canLoad:Bool = !tableView.dragging && !tableView.declearating      if  canLoad {          //开始loaddata,异步加载图片    }}

重点

  • //通过滑动,系统根据滑动判断屏幕停止时显示的位置,由此我们不用渲染中间的cell,直接渲染将要出现的cell,和下两个cell(提升用户体验)从而达到节省性能的作用.
override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {        guard let ip = tableView.indexPathForRow(at: CGPoint(x: 0, y: targetContentOffset.pointee.y)) else {            return        }        guard let cip = tableView.indexPathsForVisibleRows?.first else {            return        }        let skipCount = 12;        if labs(cip.row - ip.row) > skipCount {            guard let temp = tableView.indexPathsForRows(in: CGRect(x: 0, y: targetContentOffset.pointee.y, width: self.view.frame.width, height: self.view.frame.height)) else {                return            }            var arr = temp            print(velocity.y)            //向下滑动            if velocity.y < 0 {                let indexPath = temp.last!                if (indexPath.row + 3 < self.homeViewModel.viewmodelArray.count) {                    arr.append(IndexPath(row: indexPath.row + 1, section: 0))                    arr.append(IndexPath(row: indexPath.row + 2, section: 0))                    arr.append(IndexPath(row: indexPath.row + 3, section: 0))                }            }else{                //向上滑动                let indexPath = temp.first!                if (indexPath.row > 3) {                    arr.append(IndexPath(row: indexPath.row - 3, section: 0))                    arr.append(IndexPath(row: indexPath.row - 2, section: 0))                    arr.append(IndexPath(row: indexPath.row - 1, section: 0))                }            }            needLoadArray.append(contentsOf: arr)        }    }
//如果需要加载的数组的数量大于0 并且 正要加载的indexPath不在按需加载的数组中 就不渲染cell        if needLoadArray.count > 0 {            let result = needLoadArray.contains(where: { (index) -> Bool in                return index.row == indexPath.row && index.section == indexPath.section            })            if !result {                print("text—>  ")                return cell            }
0 0