【iOS】tableView的优化

在IOS开发中,UITableView是最重要,最常用的控件之一。而对于UITableView的优化,也是IOS开发程序员必须要思考的问题。刚好前段时间,做的一个项目就碰到有关UITableView优化,自己也找了很多资料,所以在这里整理一下我对tableView优化的理解。

1.cell的重用

UITableView中最重要的就是cell的重用机制,只要是用了UITableView控件,就必定会涉及cell的重用。cell的重用机制:当tableView显示的时候,只会创建在可视范围的cell,为了使这些cell可以重用,cell在创建的时候会有一个重用标识 ReuseIdentifier。当屏幕滚动时,有部分cell就会被移出屏幕,这些cell会被放到一个缓存池中,等待重用。当需要显示一个cell的时候,首先会到缓存池中查看有没有对应的可重用的cell,如果有,就直接拿来用,如果没有,再去创建,这样就会大大减少内存的消耗。

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: ReuseIdentifier)

    }
image.gif
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier(ReuseIdentifier, forIndexPath: indexPath)
        return cell
    }
image.gif

2.缓存行高

在呈现cell之前,把cell的高度计算好缓存起来,避免每次加载cell的时候都要计算。对于高度的计算,还有个小细节需要注意,就是如果 row 的高度都一定,那就删除代理中的这个 tableView:heightForRowAtIndexPath: 方法,设置 Table View 的 rowHeight 属性。

    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        //获得模型
        let model = models![indexPath.row]

        //判断模型里面之前有没有缓存过行高
        if model.rowHeight != nil {
            return model.rowHeight!
        }

        //自己算行高:AutoLayout
        //让 cell自己对应内容,直接获取高度,这个cell不参与显示
        let cell = tableView.dequeueReusableCellWithIdentifier(ReuseIdentifier) as! CJStatusCell
        cell.model = model

        let heigth = cell.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height

        //保存行高
        model.rowHeight = heigth
        return heigth
    }
image.gif

3.cellForRowAtIndexPath不要做耗时操作

主线程主要是用来显示UI,刷新界面的,为了不影响界面的流畅程度,耗时的操作都放到子线程去执行。

4.尽量不要去添加和移除view, 先将会用到的控件懒加载,要就显示,不要就隐藏。如果cell中有图片控件,就使用异步加载图片。

5.减少cell上subviews的数量

UITableViewCell包含了textLabel、detailTextLabel和imageView等,而你还可以自定义一些视图放在它的contentView里。然而view是很大的对象,创建它会消耗较多资源,并且也影响渲染的性能。

6.cell里面的控件,约束最好不要使用remake,动态添加约束是比较耗性能的

7.cell里面的控件,背景最好是不透明的 (图层混合), view的背景颜色 clearColor尽量少

8.图片圆角不要使用 layer.cornerRadius,图层最好不要使用阴影, 阴影会导致离屏渲染

9.异步绘制

我在这边写了一个UIImage的分类,是用来异步绘制。

import UIKit

extension UIImage {
    func cj_AsyncDrawImage(var size: CGSize?, bgColor: UIColor? = UIColor.whiteColor(), isCorner: Bool = false, drawFinish: (image: UIImage)->()) {

        let start = CACurrentMediaTime()

        if size == nil {
            //别人没有传入size
            size = self.size
        }
        //上下文大小为rect
        let rect = CGRect(origin: CGPointZero, size: size!)

        //开启上下文
        UIGraphicsBeginImageContextWithOptions(size!, bgColor != nil, UIScreen.mainScreen().scale)

        //设置背景颜色
        bgColor?.setFill()
        UIRectFill(rect)

        //需要圆角
        if isCorner {
            //路径
            let path = UIBezierPath(ovalInRect: rect)
            //让后面绘制的元素在路径里面
            path.addClip()
        }

        self.drawInRect(rect)

        //获取图片
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        //结束上下文
        UIGraphicsEndImageContext()

        let end = CACurrentMediaTime()

//        CJPrint("异步绘制时间:\(end - start)")

        //返回绘制好的图片
        dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
            drawFinish(image: newImage)
        }
    }
}
image.gif
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 我们上了一节实验课,来张纸把纸撕成了两张纸条,一个手拿一张纸条放到嘴边吹,有趣的事情就来了,本以为两张纸条能分开,...
    幸福妮_0a9e阅读 207评论 0 0
  • 车窗外一闪而过的行人,快速后退的街景,或熟悉或陌生的一隅,经年不变的公车。然后发现,视野里最亮的是倒映在车窗上的我...
    咖啡过敏患者阅读 129评论 0 0
  • 此刻的天衣,也不敢直视那方形水晶里的秦皇了。他们一行人就跪在地上,虔诚的叩拜着。在行完三拜大礼后,爷爷便开口向...
    Pan龙腾阅读 327评论 0 1
  • 幸福是一首歌,很静。如同旷野的明月,远山,近树;幸福是一首歌,很动。如同大江的波涛,飞浪,暗涌、平静中的漩涡;幸福...
    屈道秋阅读 135评论 0 0

友情链接更多精彩内容