美文网首页
iOS之UITableView学习

iOS之UITableView学习

作者: 南衍儿 | 来源:发表于2017-12-01 17:35 被阅读0次

    UITableView是iOS开发中最常用的控件,也是UIKit中相对较难的.
    在MVC模型中,UITableView属于模型中的V.

    MVC

    • 模型(Model):负责存储数据,与用户界面无关
    • 视图(View):负责显示界面,与模型无关
    • 控制器(Controller):负责确保视图对象和模型对象保持一致

    概述


    UITableView继承自UIScrollView,可以竖直方向上滚动,UITableView有两种风格,分别是UITableViewStylePlainUITableViewStyleGrouped

    UITableViewStylePlain
    UITableViewStyleGrouped

    UITableView有两个Delegate分别为:dataSource和delegate:

    • dataSource:需要实现UITableViewDataSource协议.主要为UITableView提供数据来源和提供Row的cell视图
    • delegate:需要实现UITableViewDelegate协议.提供了Header/Footer的自定义View和高度,和选中动作的回调等.

    在MVC中,提供数据给TableView的models是一个二维数组,由section和row组成,每条数据使用一个NSIndex来定位.

    有多个section(分段),section中有多个row
    NSIndex的第一维表示section,第二维表示row.

    UITableViewController


    UITableViewController是系统提供的一个便利类,主要是为了方便我们使用UITableView,该类生成的时候就将自身设置成了其包含的tableView的dataSource和delegate,并创建了很多代理函数的框架.UITableViewController可以扮演MVC中的所有角色,我们可以通过其tableView属性获取该controller内部维护的tableView对象.

    UITableViewController和UITableView的关系

    UITableViewCell


    UITableView中显示的每一个单元都是一个独立的视图对象,这些视图对象就是UITableViewCell.

    考虑到实际开发中cell可能会有很多,频繁生成cell对象是比较费时的,而且一次性生成所有cell对象可能占用太多内存.可以用以下方式来解决:

    • 只生成能看到的Cell-->解决了速度问题
    • 相似的行可以共用Cell-->解决了内存问题

    我们会发现其初始化函数-initWithStyle:reuseIdentifier:比较特别,跟我们平时看到的UIView的初始化函数不同.因为这里引入了cell的重用机制.reuseIdentifier就是指定重用的cell的布局的.相同的reuseIdentifier的cell会放在一个cell对象池中.
    系统提供的UITableView也包含了四种风格的布局,分别是:

    typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
        UITableViewCellStyleDefault,    // 左侧显示textLabel(不显示detailTextLabel),imageView可选(显示在最左边)
        UITableViewCellStyleValue1,        // 左侧显示textLabel、右侧显示detailTextLabel(默认蓝色),imageView可选(显示在最左边)
        UITableViewCellStyleValue2,        // 左侧依次显示textLabel(默认蓝色)和detailTextLabel,imageView可选(显示在最左边)
        UITableViewCellStyleSubtitle    // 左上方显示textLabel,左下方显示detailTextLabel(默认灰色),imageView可选(显示在最左边)
    };
    数据源
    
    系统默认的四种风格

    系统提供的四种并不能满足所有需求,有的时候我们需要定制自己的cell.
    UITableViewCell对象有一个子视图contenView,

    contentView(contentView不包括右边的accessoryView)

    定制自己的cell有两种方法:

    • 直接在contentView上添加子view:该方法可以在系统默认的几种cell上添加自己需要的view
    • 从UITableViewCell中派生一个类:该方法可以深度定制自己的view,也可以指定cell在进入edit模式的时候如何相应等等.

    观看这两种定制cell的方法,我们会发现subView都是添加在cell的contentView上面的,而不是直接加到cell上面,这样写也是有原因的。下面我们看一下cell在正常状态下和编辑状态下的构成图:

    正常状态下:


    编辑模式下:



    通过观察上面两幅图片我们可以看出来,当cell在进入编辑状态的时候,contentView会自动的缩放来给Editing control腾出位置。这也就是说如果我们把subView添加到contentView上,如果设置autoresizingMask为更具父view自动缩放的话,cell默认的机制会帮我们处理进入编辑状态的情况。而且在tableView是Grouped样式的时候,会为cell设置一个背景色,如果我们直接添加在cell上面的话,就需要自己考虑到这个背景色的显示问题,如果添加到contentView上,则可以通过view的叠加帮助我们完成该任务。综上,subView最好还是添加到cell的contentView中。

    编辑


    UITableView有一个editing属性,如果将该属性设置为YES.UITableView就会进入编辑模式.在编辑模式下,用户可以对UITableView中的cell进行添加,删除和移动等功能.

    增加&删除

    cell的delete和insert操作大部分流程都是一样的,当进入编辑模式的时候具体的显示是delete还是insert取决与该cell的editingStyle的值,editStyle的定义如下:

    typedef enum {
        UITableViewCellEditingStyleNone,
        UITableViewCellEditingStyleDelete,
        UITableViewCellEditingStyleInsert
    } UITableViewCellEditingStyle;
    
    

    当tableView进入编辑模式以后,cell上面显示的delete还是insert除了跟cell的editStyle有关,还与 tableView的delegate的tableView:editingStyleForRowAtIndexPath:方法的返回值有关

    delete和insert的流程如下苹果官方文档中给出的图所示:


    移动

    为了使UITableVeiew进入edit模式以后,如果该cell支持reordering的话,reordering控件就会临时的把accessaryView覆盖掉。为了显示reordering控件,我们必须将cell的showsReorderControl属性设置成YES,同时实现dataSource中的tableView:moveRowAtIndexPath:toIndexPath:方法。我们还可以同时通过实现dataSource中的 tableView:canMoveRowAtIndexPath:返回NO,来禁用某一些cell的reordering功能。


    上图中当tableView进入到edit模式的时候,tableView会去对当前可见的cell逐个调用dataSourcetableView:canMoveRowAtIndexPath:方法(此处官方给出的流程图有点儿问题),决定当前cell是否显示reoedering控件,当开始进入拖动cell进行拖动的时候,每滑动过一个cell的时候,会去掉用delegate的tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:方法,去判断当前划过的cell位置是否可以被替换,如果不行则给出建议的位置。当用户放手时本次reordering操作结束,调用dataSource中的tableView:moveRowAtIndexPath:toIndexPath:方法更新tableView对应的数据。

    IndexList


    当我们tableView中section有很多,数据量比较大的时候我们可以引入indexList,来方便完成section的定位,例如系统的通讯录程序。我们可以通过设置tableView的sectionIndexMinimumDisplayRowCount属性来指定当tableView中多少行的时候开始显示IndexList,默认的设置是NSIntegerMax,即默认是不显示indexList的。
    为了能够使用indexlist我们还需要实现dataSource中一下两个方法:

    - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView; 
    - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index; 
    

    第一个方法返回用于显示在indexList中的内容的数组,通常为A,B,C...Z。第二个方法的主要作用是根据用户在indexList中点击的位置,返回相应的section的index值。这个例子可以在苹果官方给出的TableViewSuite中找到,实现起来还是很简单的。

    相关文章

      网友评论

          本文标题:iOS之UITableView学习

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