UITableView

表视图主要用于呈现一个滚动的选择列表,在使用过程中主要有三个步骤:初始化、数据源的设置以及委托代理方法的实现。

1.UITableView简介

在UITableView中数据只有行的概念,并没有列的概念,因为在手机中显示多列是不利于操作的。

2.UITableView样式

UITableView有两种样式:平铺(UITableViewStylePlain)和分组(UITableViewStyleGrouped)。这两者本质区别不大。在没有特别设置的情况下,UITableViewStyleGrouped样式会默认留出header和footer的位置,也就是分组样式。

3.UITableView的属性

// 获取表视图的样式
@property(nonatomic, readonly) UITableViewStyle style;
// UITableView的数据源对象与代理对象,需要遵守UITableViewDataSource协议与UITableViewDelegate协议。
@property(nonatomic, weak, nullable) id<UITableViewDataSource> dataSource;
@property(nonatomic, weak, nullable) id<UITableViewDelegate> delegate;
// 单元格行高
@property(nonatomic) CGFloat rowHeight;
// 段section的header高度与footer高度。
@property(nonatomic) CGFLoat sectionHeaderHeight;
@property(nonatomic) CGFloat sectionFooterHeight;
// 整体表视图的顶部视图与底部视图
@property(nonatomic, strong, nullable) UIView *tableHeaderView;
@property(nonatomic, strong, nullable) UIView *tableFooterView;
// 索引表的字母的颜色
@property(nonatomic, strong, nullable) UIColor *sectionIndexColor;
// 索引栏的背景颜色
@property(nonatomic, strong, nullable) UIColor *sectionIndexBackgroundColor;
// 设置分割线的样式
@property(nonatomic) UITableViewCellSeparatorStyle separatorStyle;
// 定义分割线颜色
@property(nonatomic, strong, nullable) UIColor *separatorColor;

UITableView的数据源方法

在iOS开发过程中,苹果官方推荐使用MVC设计模式。视图类对象负责获取与响应用户操作,但具体的逻辑处理通常情况下是由视图对象的代理(通常为控制器对象)来完成的。对于UITableView类的对象,除了可以设置代理属性之外,还需要设置其数据源属性,因为UITableView中展示的数据是由其数据源对象提供的。在设置完UITableView的dataSource属性后,通过实现UITableViewDataSource协议中定义的数据源方法来为UITableView对象提供需要展示的数据。

在UITableView中,引入了NSIndexPath类来定位每一个单元格。在NSIndexPath类中,包含两个关键属性:section与row,分别对应每个单元格在UITableView中段号Section与行号Row。根据索引路径indexPath即可定位到唯一的一个单元格。

@interface NSIndecPath (UITableView)
@property(nonatomic, readonly) NSInteger section;
@property(nonatomic, readonly) NSInteger row;
@end

UITableViewDataSource中的常用方法

// (必选)返回每个段(seciton)中有多少个单元格。
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
// (必选)返回每个单元格的具体样式和显示内容。
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
//(可选)返回整个表视图有多少个段(section),如果不实现该方法,默认为1个段。
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;

UITableViewDataSource中的其他方法
// 设置某section上header的标题,当tableview的style是平铺时有悬浮效果,为分组时是没有悬浮效果的。
-(nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSinteger) section;
// 设置每个段section上的footer的标题。
-(nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger) section;
// 设置表视图的索引。
-(nullable NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView;
// 点击右侧索引栏时调用。
-(NSInteger)tableView:(UITableView *)tableView sectionForSectionTitle:(NSString *)title atIndex:(NSInteger)index;
// 对单元格进行编辑(删除、添加)时调用。
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle) editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
// 设置单元格是否可移动。
-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;
// 对单元格的移动。
-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)dextinationIndexPath;

单元格UITableViewCell

单元格(UITableViewCell)是UITableView的组成单元,每一个单元格都是一个UITableViewCell对象。默认情况下,一个单元格具有1个icon图片、1个title、1个detail title以及1个accessory。

系统自带的单元格(即UITableViewCell类型的)主要有以下4个常用属性。

imageView:显示在左边的一张图片logo。
textLabel:主要文字,黑色字体显示,textLabel和detailTextLabel会在上图中的Text处显示。
detailTextLabel:详细说明文字,字体较小。
accessaryView:附件视图,可以使用自定义View,也可以使用系统自带的一些标准按钮。

// 默认情况下,系统自带了4种样式的单元格,区别在于显示的属性内容以及位置不同。
UITableViewCellStyleDefault:默认样式;
UITableViewCellStyleValue1;
UITableViewCellStyleValue2;
​​​​​​​UITableViewCellStyleSubtitle:带子标题的样式。

Accessory View是显示在单元格最右边的图标,主要可以用来显示一些提示信息,默认情况下是不显示的。

当需要显示Accessory View时,可以有两种方式来设置。通过cell的accessoryType属性设置。
@property(nonatomic)UITableViewCellAccessoryType accessoryType;
通过cell的accessoryView属性来自定义附件的样式。
@property(nonatomic, strong, nullable) UIView *accessoryView;

UITableView创建示例

@interface ViewController ()<UItableViewDelegate, UITableViewDataSource>
@property(nonatomic, strong) UITableView *tableView;
@end
// 对tableView属性进行懒加载,设置表视图的属性。
-(UITableView *)tableView {
    if (_tabelView == nil) {
        _tableView = [[UITaleView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
        _tableView.dataSource = self;
    }
    return _tableView;
}
// 实现UITableViewDataSource协议中的tableView: numberOfRowsInSection:方法,返回表视图中包含的单元格个数
-(NSInteger)tableView:(UITableVIew *)tableView numberOfRowsInSection:(NSInteger)section {
    return 20;
}
// 实现tableView: cellForRowAtIndexPath:方法,创建每一个单元格
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath {
    static NSString *dellID = @"cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIndetifier:cellID];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:cellID];
    // 获取随机数据
    NSString *text = [NSString stringWithFormat:@"%d", arc4random_uniform(1000000)];
    // 设值
    cell.textLabel.text = text;
    return cell;
    }
}

UITableView代理方法之点击单元格

1.UITableView监听用户点击动作的常用方法
// 用户点击单元格时调用。
-(nullable NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath;
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSindexPath *)indexPath;
// 取消单元格选中调用。
-(nullable NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowIndexPath:(NSIndexPath *)indexPath;
-(void)tableView:(UITableView *)tableView dedDeselectRowAtIndexPath:(NSIndexPath *)indexPath;
// 单元格高亮显示。
-(BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPAth;
-(void)tableView:(UITableView *)tableView didHighlightRowAtIndexParh:(NSIndexPath *)indexPath;
-(void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath;

UITableView代理方法之编辑单元格

1.单元格Cell编辑方法
在UITableViewDelegate协议中,定义了如下几个与单元格修改相关的方法,当需要对单元格进行修改时,会调用对应的方法。
// 设置对单元格修改时添加的按钮及其对应的处理事件。
-(nullable NSArray<UITableViewRowAction *>*)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath;
// 开始编辑单元格前调用的方法。
-(void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath;
// 完成编辑单元格后调用的方法。
-(void)tableView:(UITableView *)tableView didEditingRowAtIndexPath:(NSIndexPath *)indexPath;
2.UITableViewRowAction简单介绍
UITableViewRowAction对象是用于设置UITableViewCell处于编辑状态下所显示的按钮。默认情况下,左滑会显示一个删除按钮,也可以创建多个UITableViewRowAction对象从而实现不同的操作
// UITableViewRowAction对象的创建可以调用API中定义的类方法
+(instancetype)rowActionWithStyle:(UITableViewRowActionStyle)style title:(nullable NSString *)title handler:(void (^)(UITableViewRowAction *action, NSIndexPath *indexPath))handler;
// 除此之外,UITableViewRowAction对象还可以设置它的背景颜色backgroundColor,其title属性也可以被修改。
@property(nonatomic, copy, nullable) NSString *title;
@property(nonatomic, copy, nullable) UIColor *backgroundColor;

3.实现单元格编辑的基本步骤

当需要对单元格进行编辑时,可以按照如下的步骤进行实现。

实现editActionsForRowAtIndexPath:方法。
创建UITableViewRowAction对象,并设置每个按钮对应的操作。
调用reloadData方法刷新表格:对tableview的cell进行操作后,一定记得需要重新刷新表格,更新样式。

-(nullable NSArray<UITableViewRowAction *>*)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewRowAction *action1 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"添加" habdler:nil];
    UITableViewRowAction *action2 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"移动" habdler:nil];
    UITableViewRowAction *action3 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"删除" habdler:^(UITableViewRowAction*_Nonnul action, NSIndexPath*_Nonnull indexPath){
        NumberGroup *numberGroup = self.dataList[indexPath.section];
        [numberGroup.groupNumbers removeObjectAtIndex:indexPath.row];
        [tableView reloadData];
    }];
    NSArray *actionArray = @[action1, action2, action3];
    return actionArray;
}

UITableViewCell性能优化

UITableView中的单元格cell是在表视图显示到用户可视区域后创建的,如果用户向下滚动就会继续创建UITableViewCell对象,同时,假如用户向上滚动返回之前已经查看的内容时,同样也会重新创建新的UITableViewCell对象。即便是表视图UITableView的内容不是很多的情况下,如果用户反复上下滚动,内存也会快速增加。另外,在诸如微博此类应用中,用户向下滑动可能加载的单元格数量是无限的。出于对内存空间利用效率方面的考虑,在UITableView中,可以动态切换cell的内容来尽可能减少资源占用,将当前没有显示的cell重新显示在将要显示的cell的位置然后更新其内容。在创建一个单元格时,需要根据单元格的样式类型为其指定一个可重用标识ID,当单元格移除屏幕后,该单元格对象会被暂时存放在缓存池中,即将被显示的单元格,会优先在缓存池中查找可重用标识ID一致的单元格,如果有相同的单元格,则直接复用,如果没有找到同样可重用标识的单元格才会重新创建。UITableView内部的缓存池机制是保证表视图高效响应用户交互的一个重要机制。在UITableViewCell类中,定义了与缓存池机制密切相关的实例化方法。可重用标识可以有多个,如果在UITableView中有多类结构不同的Cell,可以通过这个标识进行缓存和重用。

// 根据可重用标识从缓存池中查找相同标识的单元格。
-(nullable __kinfof UITableViewCell *)dequeueReuseableCellWithIdentifier:(NSString *)identifier;
// 创建单元格,并指定其可重用标识。
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(nullable NSString *)reuseIdentifier;

8 分段Section

在UITableViewDataSource协议中,如果涉及多个Section的配置,则需要实现如下方法。如不实现,则seciton的默认值为1,即整个表视图只有一个段Section。
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;

// 设置header的标题
-(nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSinteger) section;
// 设置footer的标题。
-(nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:
// 定制Section顶部视图样式
-(nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSinteger)section;
// 定制Section底部视图样式
-(nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSinteger)section;

// 索引显示的内容需要通过sectionIndexTitlesForTableView:数据源方法来实现,索引内容需要存放在一个数组中作为该方法的返回值,数组中的每个对象都与一个Section对应。
-(nullable NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;
// 索引文字颜色
@property(nonatomic, strong, nullable) UIColor *sectionIndexColor;
// 索引背景颜色
@property(nonatomic, strong, nullable) UIColor *sectionIndexBackgroundColor;
// 索引点击时的背景颜色
@property(nonatomic, strong, nullable) UIColor *sectionIndexTrackingBackgroungColor;
exp:
@interface ViewController ()<UITableViewDataSource, UITableViewDelegate>
@property(nonatomic, strong)UITableView *tableView;
@end

-(UITableView *)tableView {
    // 懒加载初始化UITableView
    if (_tableView == nil) {
        _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 20. [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) style:UITableViewStyleGround];
        // 设置代理和数据
        _tableView.delegate = self;
        _tableView.dataSource = self;
        // 分割线与屏幕等宽
        _tableView.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0);
        // 分割线颜色
        _tableView.separatorColor = [UIColor blackColor];
        // 索引兰颜色
        _tableView.sectionIndexBackgroundColor = [UIColor clearColor];
        // 索引文字颜色
        _tableView.sectionIndexColor = [UIColor redColor];
    }
    return _tableView;
}
通过实现tableView:titleForHeaderInSection:以及tableView:titleForFooterInSection:可以实现对每个Section的文字头部以及文字底部进行定制。
// 设置Section的header文字
-(NSString *)tableView:(UITableView *)tableView titleForHeaderSection:(NSString *)section {
    NSString *message = [NSString stringWithFormat:@"第%ld个Section头部", (long)section];
    return message;
}
为Section设置自定义header和footer
// 定制头部视图样式。
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 30)];
    headerView.backgroundColor = [UIColor orangeColor];
    return headerView;
}
// 通过实现sectionIndexTitlesForTableView:方法即可实现索引内容的定制,该方法的返回值是一个数组,并且数组中存储的都是字符串类型的对象。

自定义Cell

// 创建自定义单元格类
@interface MYTableViewCell ; UITableViewCell
+(interfacetype) cellWillTableView:(UITableView *)tableView;
@end

Cell高度的设置

// 修改rowHeight属性。当单元格的高度为固定值时,可以使用rowHeight属性来设置单元格的高度。
@property(nonatomic) CGFloat rowHeight;
// 在heightForRowAtIndexPath:代理方法中设置单元格的高度。tableView:heightForRowAtIndexPath:
-(CGFloat)tableView:(UITableView *)tabeView heightForRowAtInedxPath:(NSindexPath *)indexPath;

动态调整Cell高度

// 设置表视图的estimatedRowHeight属性,即单元格的预估行高,一般设置为单元格的默认行高。
@property(nonatomic)CGFloat estimatedRowHeight;
// 在tableView:heightForRowAtIndexPath方法中,取出数据模型对象中的cellLabelHeight属性,并作为单元格Cell的高度返回。
-(CGFloat)tableView:(UITableView *)tabeView heightForRowAtInedxPath:(NSindexPath *)indexPath {
    MYModel *cellData = self.dataArray[indexPath.row];
    return cellData.cellLableHeight;
}

UITableView+FDTemplateLayoutCell计算Cell高度

当使用UITableView+FDTemplateLayoutCell框架时,有3个使用步骤。

使用自动布局为单元格中的子控件添加完整的边界约束("top"、"left"、"bottom"、"right")。当使用dequeueReusableCellWithIdentifier:方法从缓存池中查找单元格对象之前,需要提前注册单元格,单元格的注册方法有如下两个,分别对应使用代码以及XIB创建单元格。

在tableView:heightForRowAtIndexPath:方法中,调用UITableView+FDTemplateLayoutCell中的fd_heightForCellWithIdentifier:configuration:方法,即可实现单元格的动态高度调整。

-(void)registerNib:(nullable UINib *)nib forCellReuseIdentifier:(NSString *)identifier;
-(void)registerClass:(nullable Class)cellClass forCellReuseIdentifier:(NSString *)identifier;

-(CGFloat)fd_heightForCellWithIdentifier:(NSString *)identifier configuration:(void (^)(id cell))configuratuon;

改变Cell位置

如果需要调整Cell的位置,首先需要设置表视图的editing属性为YES。

另外,还需要添加tableView:moveRowAtIndexPath:toIndexPath:代理方法,在该方法中,可以获取单元格的原索引位置sourceIndexPath以及更新后的索引位置destinationIndexPath,通过这两个属性,需要去修改该单元格对应的数据在数据源数组中的位置,以便再次刷新界面后,该单元格的显示顺序是不变的。

@property(nonatomic, getter=isEditing) BOOL editing;
-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;

UITableView的Header和Footer

每一个UITableView对象都有一个tableHeaderView属性和一个tableFooterView属性,这两个属性是对应整个表视图的顶部视图和底部视图。需要注意同Section的HeaderView以及FooterView进行区分。

// UITableView的顶部视图和底部视图要通过属性tableHeaderView和tableFooterView来设置。
@property(nonatomic, strong, nullable) UIView *tableHeaderView;
@property(nonatomic, strong, nullable) UIView *tableFooterView;

去除多余的单元格分割线

当单元格Cell的数量不够覆盖整个屏幕的时候,系统默认情况下,会自动添加一些分割线,而有时程序员并不希望显示这些分割线,因此可以利用tableFooterView来去除这些分割线。

// 去除多余的单元格分割线的设置方法如下,初始化一个空的UIView对象,并把其赋值给表视图的tableFooterView属性。
// 
UIView *view = [UIView new];
view.backgroundColor = [UIColor clearColor];
self.tableView.tableFooterView = view;

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在UITableView的section中添加数据,你需要先创建一个包含所需数据的数组。然后,在UITableViewDataSource协议中实现以下方法: 1. numberOfSections(in tableView: UITableView) -> Int:返回表格中的section数。 2. tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int:返回指定section中的行数。 3. tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell:返回指定indexPath的UITableViewCell实例。 例如,假设你有一个包含多个section的UITableView,每个section都包含一个字符串数组。以下是一个示例代码: ``` class ViewController: UIViewController, UITableViewDataSource { var data: [[String]] = [["item 1", "item 2"], ["item 3", "item 4", "item 5"]] @IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() tableView.dataSource = self } // MARK: - UITableViewDataSource func numberOfSections(in tableView: UITableView) -> Int { return data.count } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return data[section].count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = data[indexPath.section][indexPath.row] return cell } } ``` 在这个例子中,我们创建了一个包含两个section的UITableView。每个section都有一个字符串数组,我们将其存储在data数组中。在numberOfSections方法中,我们返回data数组的数量,即section的数量。在tableView(_:numberOfRowsInSection:)方法中,我们返回特定section中的行数。最后,在tableView(_:cellForRowAt:)方法中,我们获取特定indexPath的字符串并将其显示在UITableViewCell中。 注意,在上述示例代码中,我们将UITableViewCell标识符设置为“Cell”,你需要确保在Storyboard或xib文件中对应的UITableViewCell的标识符也设置为“Cell”。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值