【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)
        
    }
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier(ReuseIdentifier, forIndexPath: indexPath)
        return cell
    }

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
    }

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)
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_34716474/article/details/51190676