UITableView和UITableViewCell

UITableView

简单plain 分组grouped

数据展示条件

UITableView的所有数据都是由数据源(dataSource)提供的,所以想要在UITableView展示数据,必须设置UITableView的dataSource数据源对象
要想当UITableView的dataSource对象,必须遵守UITableViewDataSource协议,实现相应的数据源方法
当UITableView想要展示数据的时候,就会给数据源发送消息(调用数据源方法),UITableView会根据方法返回值决定展示怎样的数据

数据展示过程

1、 调用数据源方法获取一共有多少组

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;

2、调用数据源方法获取第section组一共有多少行

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;

3、调用数据源方法第indexPath.section组的第row行显示怎样的cell(显示什么内容)(当一个cell出现在视野范围内的时候才会被调用)

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

常用数据源方法

// 一共有多少组
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;  
// 第section组一共有多少行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
// 第indexPath.section组的第row行显示怎样的cell(显示什么内容)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
// 第section组显示怎样的头部标题
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;    
// 第section组显示怎样的尾部标题
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
// 侧边栏标题
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView

更改UITableView每行高度

1、设置rowHeight属性(每行高度一致)

@property (nonatomic) CGFloat  rowHeight;

2、通过实现代理中声明的方法返回每一行的高度(每行高度可以不一致)

@property (nonatomic, assign) id <UITableViewDelegate> delegate;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;

UITableView头尾视图

UITableView头尾View默认宽度self.bounds.size.width,默认高度0,且默认宽度无法更改!

// 头视图
@property (nonatomic, retain) UIView *tableHeaderView; 
// 尾视图 
@property (nonatomic, retain) UIView *tableFooterView;   

设置头尾视图代理方法:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section; - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section; 

执行tableView数据重载时,头尾视图从重用缓冲区中无法获取,系统会重新创建一个新的头尾视图,这点与tableViewCell不一样,tableViewCell依然可以从重用缓冲区获取。也说明了头尾视图的重用是在滚动的时候体现。

自定义头尾视图可能需要的方法:

// 该方法在控件的frame被更改时被调用,一般用于调整子控件的位置
// 由于在头尾视图代理方法返回对应的头尾视图后,系统会自动设置头尾视图的frame,所以此方法会被调用,可以用于调整子控件的位置
- (void)layoutSubviews; 

//当一个控件被添加到其它视图上的时候会调用以下方法
// 已经被添加到父视图上的时候会调用
// 由于执行tableView数据重载时,系统会重新获取全新的头尾视图,可以在新视图加入父视图前后做一些动作
- (void)didMoveToSuperview
// 即将被添加到父视图上的时候会调用
- (void)willMoveToSuperview:(UIView *)newSuperview  

重载UITableView中的数据:

// 重载TableView中的所有数据                                                                                          
- (void)reloadData; // 重载指定段(可选择系统动画效果) - (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation; // 重载指定段的指定行(NSIndexPath * 的数组)(可选择系统动画效果) - (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation; 

设置特殊子控件高度:

由于tableView一般给子视图设置了默认的frame,所以设置tableView的footerView、HeaderView或者cell的高度,只能用tableView对应的高度属性或者提供的代理方法:

// 自身属性
@property (nonatomic)          CGFloat                     rowHeight; 
@property (nonatomic)          CGFloat                     sectionHeaderHeight; 
@property (nonatomic)          CGFloat                     sectionFooterHeight; 
// 代理方法
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;

滚动到指定行:

- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;

UITableViewCell

backgroundColor和backgroundView的异同

通过backgroundColor和backgroundView都可以实现设置cell的背景颜色,但backgroundView的优先级比backgroundColor高,同时设置时,backgroundView会覆盖住backgroundColor。另外backgroundView也可以设置背景图片

UITableViewCell结构

UITableView和UITableViewCell_第1张图片
contentView是cell中的imageView、labelView、detailTextLabel的父视图

UITableViewCell重用

原理:
首先,以下方法是在一个cell出现在视野范围内的时候才会被调用的

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

当滚动列表时,部分UITableViewCell会移出窗口,UITableView会将窗口外的UITableViewCell放入一个对象池中,等待重用。当UITableView要求dataSource返回UITableViewCell时,dataSource会先查看这个对象池,如果池中有未使用的UITableViewCell,dataSource会用新的数据配置这个UITableViewCell,然后返回给UITableView,重新显示到窗口中,从而避免创建新对象

可能发生的问题:
有时候需要自定义UITableViewCell(用一个子类继承UITableViewCell),而且每一行用的不一定是同一种UITableViewCell,所以一个UITableView可能拥有不同类型的UITableViewCell,对象池中也会有很多不同类型的UITableViewCell,那么UITableView在重用UITableViewCell时可能会得到错误类型的UITableViewCell

解决方法:
UITableViewCell有个NSString *reuseIdentifier属性,可以在初始化UITableViewCell的时候传入一个特定的字符串标识来设置reuseIdentifier(一般用UITableViewCell的类名)。当UITableView要求dataSource返回UITableViewCell时,先通过一个字符串标识到对象池中查找对应类型的UITableViewCell对象,如果有,就重用,如果没有,就传入这个字符串标识来初始化一个UITableViewCell对象

问题归纳:
UITableViewCell重用注意:通过xib自定义cell时,注意要添加identifier,以便创建时能根据ID从缓存中获取

从缓存中获取已存在的cell方法:

// UITableView
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier; 

代码示范:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 1.定义一个cell的标识
      static NSString *ID = @”rwcell";

    // 2.从缓存池中取出cell
      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    // 3.如果缓存池中没有cell
      if (cell == nil) {
        // 创建cell并添加可重用标识
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
    }

    // 4.设置cell的属性...

    return cell;
}

通过xib自定义cell步骤

自定义cell:
1. 创建一个xib,在xib中描述界面
2. 创建一个继承于UITableViewCell的类,修修改xib的custom class(loadNib时创建的类),由这个类管理xib
3. 在自定义类中提供一个类方法,快速创建一个cell
4. 在自定义中定义一个模型属性,由外界传入,内部赋值

cell操作注意事项:

UITableViewCell或者自定义cell子类中有操作1(隐藏)一定要有操作 2(显示)[操作2和操作1相反],以便cell重用时不会发生设置后无法返回原样问题

你可能感兴趣的:(UITableView和UITableViewCell)