美文网首页swift学习iOS点点滴滴iOS Developer
【iOS 开发】tableView updates 对比 rel

【iOS 开发】tableView updates 对比 rel

作者: KyXu | 来源:发表于2016-10-11 19:06 被阅读4303次
    Paste_Image.png

    如图有一个 TableView,每行显示这一行是第几行,现在我希望每按一次 update 按钮,就动态地在下方加两行。那么简单粗暴的做法是 ,更改数据源,然后刷新一下列表:

    // tableData = ["0", "1", "2", "3"]
    @IBAction func update(_ sender: AnyObject) {
        tableData.append("\(tableData.count)")
        tableData.append("\(tableData.count)")
        tableView.reloadData()
    }
    

    用膝盖想也知道,这会使得前四行没有被改动的地方也被刷新一遍,带来了不必要的性能损耗。
    好一点的做法是下面这样的:

    // tableData = ["0", "1", "2", "3"]
    @IBAction func update(_ sender: AnyObject) {
        tableData.append("\(tableData.count)")
        tableData.append("\(tableData.count)")
        tableView.beginUpdates()
        let indexPaths = [IndexPath(row: tableData.count-2, section: 0), IndexPath(row: tableData.count-1, section: 0)]
        tableView.insertRows(at: indexPaths, with: UITableViewRowAnimation.automatic)
        tableView.endUpdates()
    }
    

    与上面相比,这样做使得 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 方法被少调用了四次。

    这里 beginUpdatesendUpdates 方法的作用是,将这两条语句之间的对 tableView 的 insert/delete 操作聚合起来,然后同时更新 UI。鉴于我这里只进行了一次 insert 操作,把这两条语句去掉也没事,但是出于规范还是应该写上,因为假如习惯不写,下面这样的代码会运行时崩溃:

    @IBAction func update(_ sender: AnyObject) {
        tableData.append("\(tableData.count)")
        tableData.append("\(tableData.count)")
        //        tableView.beginUpdates()
        tableView.insertRows(at: [IndexPath(row: tableData.count-2, section: 0)], with: UITableViewRowAnimation.automatic)
        tableView.insertRows(at: [IndexPath(row: tableData.count-1, section: 0)], with: UITableViewRowAnimation.automatic)
        //        tableView.endUpdates()
    }
    

    因为第一次 insert 之后,当前 row 的总数量在 UI 上试图 4 变成 5,然而数据源是 6,它会检查使用者对 tableView 的 UI 操作,最后是不是和 numberOfRows 方法获取的值相对应。

    总结

    numberOfRows 方法调用: 都只调用一次 numberOfRows 方法

    cellForRow 方法调用次数: reloadData 会为当前显示的所有cell调用这个方法,updates 只会为新增的cell调用这个方法
    cellForRow 方法调用时间: reloadData 会在 numberOfRows 方法调用后的某一时间异步调用 cellForRow 方法,updates 会在 numberOfRows 方法调用后马上调用 cellForRow 方法

    reloadData 方法缺陷: 带来额外的不必要开销,缺乏动画
    updates 方法缺陷:deleteRows 不会调用 cellForRow 方法,可能导致显示结果与数据源不一致;需要手动保证 insertRows、deleteRows 之后,row 的数量与 numberOfRows 的结果一致,否则会运行时崩溃


    部分文章中没有写,总结提到了的部分放在完整 demo 里面了:demo Github 地址

    相关文章

      网友评论

      • 吃蘑菇De大灰狼:Good,详细的介绍了table的Update这个方法,一些不需要全局刷新的需求很方便~
      • llllllllIllllIl:tableviewcell效率还可以扩充,真的,如果谁想继续写下去,请@我,我会过去评论的。
      • unhangcorn:好人一生平安
      • 3e0349b2aec0:您好 在么 endUpdates()会调用cellForRow的方法么? 我看api说不会调用,但是为什么我这里走完endUpDates先去调用numberRow 再去调用cellForRow的方法啊

      本文标题:【iOS 开发】tableView updates 对比 rel

      本文链接:https://www.haomeiwen.com/subject/qyubyttx.html