UITablerView(表视图基础)


一:UITableView的代理,数据源代理

二:UITableView的单组数据与多组数据的展示

三:UITableViewCell的常见属性以及Cell重用机制


1:UITableView是开发中用到频率最高的视图控件。

要使用UITableView显示数据必须设置其的代理以及数据源代理,没有设置代理预计数据源代理的UITableView都是空壳。


遵守代理

@interface ViewController ()<UITableViewDelegate,UITableViewDataSource>


@property(nonatomic,strong)UITableView *tabelView;



-(void)settableView

{

    

    //UITableViewStylePlain 一般样式

    //UITableViewStyleGrouped 分组样式

    self.tabelView = [[UITableViewalloc]initWithFrame:self.view.boundsstyle:(UITableViewStylePlain)];

    //代理

    self.tabelView .delegate =self;

    //数据源

    self.tabelView.dataSource =self;

    

}


#pragma MARK  __实现数据源代理与代理中必须实现的方法__


/**

 UITableView中有几个分区


 @param tableView 哪个tableView

 @return 分区数NSInteger

 */

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

{

    return1;

}


/**

 每个分区中有几行


 @param tableView 哪个tableView

 @param section 哪个section

 @return 行数NSInteger

 */

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

{

    return10;

}


/**

 设置如何显示数据


 @param tableView 哪个tableView

 @param indexPath 哪个indexPath

 @return 返回的行视图

 */

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

{

    //重用标识

    NSString * ReusabelIdentifier =@"ReusabelIdentifier";

    //从缓存中获取cell

    UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:ReusabelIdentifier];

    //如果缓存中没有对应IDcell

    if(cell ==nil)

    {//申请内存根据重用标识创建一个cellcell会加入内存中,在需要的时候进行重用


//UITableViewCellStyleDefault,

        

       // UITableViewCellStyleValue1,

        

       // UITableViewCellStyleValue2,

        

        //UITableViewCellStyleSubtitle


        cell = [[UITableViewCellalloc]initWithStyle:(UITableViewCellStyleDefault)reuseIdentifier:ReusabelIdentifier];

    }

    //设置cell上显示什么

    cell.textLabel.text =@"cellContent";

    return cell;

}

/*

 dataSourceUITableViewDataSource类型,主要为UITableView提供显示用的数据(UITableViewCell),指定UITableViewCell支持的编辑操作类型(insertdeletereordering),并根据用户的操作进行相应的数据更新操作,如果数据没有更具操作进行正确的更新,可能会导致显示异常,甚至crush

 

 delegateUITableViewDelegate类型,主要提供一些可选的方法,用来控制tableView的选择、指定section的头和尾的显示以及协助完成cell的删除和排序等功能。

 

 提到UITableView,就必须的说一说NSIndexPathUITableView声明了一个NSIndexPath的类别,主要用来标识当前cell的在tableView中的位置,该类别有sectionrow两个属性,前者标识当前cell处于第几个section中,后者代表在该section中的第几行。

 UITableView只能有一列数据(cell),且只支持纵向滑动,当创建好的tablView第一次显示的时候,我们需要调用其reloadData方法,强制刷新一次,从而使tableView的数据更新到最新状态。

 */


UITabelView的其他常用代理方法


/**

 cell即将被显示的时候调用 在这里可以对cell内容进行进一步的修改


 @param tableView 哪个UITabelView

 @param cell 哪个cell

 @param indexPath 哪个indexPath

 */

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

{

    

}


/**

 cell已经完成显示的以后调用。


 @param tableView 哪个UITableView

 @param cell 哪个cell

 @param indexPath 哪个indexPath

 */

- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath

{

    

}


/**

 当分区的头部视图即将显示的时候调用 在这里对头部视图进行进一步的修改


 @param tableView 哪个UITableView

 @param view 哪个头部视图

 @param section 哪个分区

 */

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section

{

    

}



/**

 当分区视图显示完成之后会调用


 @param tableView 哪个UITableView

 @param view 哪个头部视图

 @param section 哪个分区

 */

- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section

{

    

}


/**

 当分区的尾部视图即将显示的时候调用 在这里对尾部视图进行进一步修改


 @param tableView 哪个UITableView

 @param view 哪个尾部视图

 @param section 哪个分区

 */

- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section

{

    

}


/**

 当尾部视图完成显示的时候调用


 @param tableView 哪个UITableView

 @param view 哪个尾部视图

 @param section 哪个分区的

 */

- (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section

{

    

}


// Variable height support



/**

 设置cell的高度


 @param tableView 哪个UITableView

 @param indexPath 哪个indexPath

 @return 高度

 */

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

    return  99.0;

}



/**

 返回分区头部视图的高度


 @param tableView 哪个UITableView

 @param section 哪个分区的

 @return 高度

 */

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section

{

    return 120.0;

}



/**

 设置分区尾的高度


 @param tableView 哪个UITableView

 @param section 哪个分区

 @return 高度

 */

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section

{

    return 120.0;

}



/**

 返回cell的预计高度


 @param tableView 哪个UITableView

 @param indexPath 哪个indexPath

 @return 高度

 */

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath

{

    return 30.0;

}



/**

 返回头部视图的预计高度


 @param tableView 哪个UITableView

 @param section 那个分区

 @return 哪个indexPath

 */

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section

{

    return 44.0;

}


/**

 返回尾部视图的预计高度


 @param tableView 哪个UITableView

 @param section 哪个分区

 @return 哪个indexPath

 */

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section {

    return 60.0;

}




/**

返回每个分区的头部视图


 @param tableView 哪个UITableView

 @param section 哪个分区

 @return 返回的视图

 */

- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

{

    UIView * headView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 44.0)];

    [headView setBackgroundColor:[UIColor redColor]];

    

    return headView;

}


/**

 返回的尾部视图


 @param tableView 哪个UITableView

 @param section 哪个分区

 @return 返回的视图

 */

- (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section

{

    UIView * footerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 44.0)];

    [footerView setBackgroundColor:[UIColor greenColor]];

    

    return footerView;

}



/**

 返回每个Cell的附件样式


 @param tableView 哪个UITableView

 @param indexPath 哪个indexPath

 @return 返回附件样式

 */

- (UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath

{

    

//    UITableViewCellAccessoryNone

    

//    UITableViewCellAccessoryDisclosureIndicator

    

//    UITableViewCellAccessoryDetailDisclosureButton

    

//    UITableViewCellAccessoryCheckmark

    

//    UITableViewCellAccessoryDetailButton

    

    return UITableViewCellAccessoryNone;

    

}


/**

 当样式按钮点击的时候调用


 @param tableView 哪个UITableView

 @param indexPath 哪个indexPath

 */

- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath


{

    

}



/**

 cell是否能被高亮


 @param tableView 哪个UItableView

 @param indexPath 哪个indexPath

 @return YES OR NO

 */

- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath

{

    return YES;

}



/**

 cell已经高亮的时候调用


 @param tableView 哪个UITableView

 @param indexPath 哪个indexPath

 */

- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath

{

    

}


/**

 即将失去高亮的时候调用


 @param tableView 哪个UITableView

 @param indexPath 哪个indexPath

 */

- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath

{

    

}



/**

 cell即将被选择的时候调用


 @param tableView 哪个UITableView

 @param indexPath 哪个indexPath

 @return 返回的indexPath

 */

- (nullable NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath{

    return indexPath;

}


/**

 cell即将失去选择的时候调用 用于获取失去选择的indexPath


 @param tableView 哪个UITabelView

 @param indexPath 哪个indexPath

 @return indexpath

 */

- (nullable NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath

{

    return indexPath;

}




/**

 cell被选择的时候调用


 @param tableView 哪个UITabelView

 @param indexPath 哪个indexPath

 */

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

    //doing something when the cell be selected

}


/**

 cell失去选择的时候调用


 @param tableView 哪个UITableView

 @param indexPath 哪个indexPath

 */

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath

{

    //doing something when the cell deselect

}


// Editing


/**

 返回cell的编辑类型(需要开启编辑功能)


 @param tableView 哪个UITableView

 @param indexPath 哪个indexPath

 @return 返回的编辑类型

 */

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath

{

    //无类型

   // UITableViewCellEditingStyleNone,

    //删除类型

    //UITableViewCellEditingStyleDelete,

    //插入类型

    //UITableViewCellEditingStyleInsert

    

    return UITableViewCellEditingStyleNone;


}



/**

 返回编辑Confirmation按钮的title


 @param tableView 哪个UITableView

 @param indexPath 哪个indexPath

 @return 返回的title

 */

- (nullable NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath

{

    return @"Confirmation";

}



/**

 返回每个Confirmation按钮点击之后需要执行的action,不需要系统默认操作的时候使用


 @param tableView 哪个UITableView

 @param indexPath 哪个indexPath

 @return 返回的UITableViewRowAction类型数组。

 */

- (nullable NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath

{

    

    UITableViewRowAction *action = [UITableViewRowAction rowActionWithStyle:(UITableViewRowActionStyleDefault) title:@"action" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {

        //

        NSLog(@"action");

    }];

    

    return [NSArray arrayWithObjects:action, nil];

}



/**

 是否允许cell编辑的时候缩进


 @param tableView 哪个UITableView

 @param indexPath 哪个indexPath

 @return YES OR NO

 */

- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath

{

    return NO;

}



/**

 cell即将开始编辑的时候调用


 @param tableView 哪个UITableView

 @param indexPath 哪个indexPath

 */

- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath

{

    

}


/**

 cell完成编辑的时候调用


 @param tableView 哪个UITableView

 @param indexPath 哪个indexPath

 */

- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(nullable NSIndexPath *)indexPath

{

    

}


这些代理方法不必全部熟悉,用到的时候跳进头文件中进行查看,要学会从文档中找到自己需要的东西。

 

UITableViewCell的使用

给cell赋值数据对象。建议先熟悉MVC模式

MVC是一种设计思想,贯穿于整个iOS开发中,需要积累一定的项目经验,才能深刻体会其中的含义和好处

MVC中的三个角色

M:Model,模型数据

V:View,视图(界面)

C:Control,控制中心

注意:首先控制器会加载这个数据,然后根据这个数据的个数去创建对应的view

 

MVC的几个明显的特征和体现:

View上面显示什么东西,取决于Model

只要Model数据改了,View的显示状态会跟着更改

Control负责初始化Model,并将Model传递给View去解析展示


Cell的简介以及属性

UItableView的每一行都是一个UITableViewCell,通过datasoure的

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;方法进行编辑(该方法就是UITaleView重用机制的一个初始化cell的系统提供的方法)


UITableView内部有一个默认的字视图contentView,contentView是cell上面视图的父视图,可以显示一些辅助控件

accessoryType属性:(辅助指示视图)

辅助指示视图的作用是显示一个表示动作的图标,可以设置UITableView的accessoryType来显示。默认是不现实辅助指示图的


 // UITableViewCellAccessoryNone,(不显示辅助视图)

        

//UITableViewCellAccessoryDisclosureIndicator(箭头)

        

// UITableViewCellAccessoryDetailDisclosureButton(按钮+箭头)

        

        

// UITableViewCellAccessoryCheckmark(对勾)

        

//UITableViewCellAccessoryDetailButton(感叹号)

        

[cell setAccessoryType:(UITableViewCellAccessoryDetailButton)];


 Cell的常见属性

 设置cell的背景颜色 backgroundColor优先级低于backgroundView

backgroundView使用方法:

  创建一个View

 UIView *bg = [[UIView alloc] init];

 设置view的颜色,然后简介的给cell赋值

 bg.backgroundColor = [UIColor redColor];

  再设置cell背景的颜色

 cell.backgroundView = bg;

 

 selectedBackgroundView 使用方法:

  创建一个View(也可以设置UIImageView作为cell的背景颜色)

 UIView *selectedView = [[UIView alloc] init];

 设置view的颜色,然后间接的赋值给cell

 selectedView.backgroundColor = [UIColor redColor];

     

还可以通过cell的accessoryView属性来自定义辅助指示视图(比如往右边放一个开关)

注意:这里的cell的指的是通过UITableViewCell创建的一个对象的accessoryView属性来自定义辅助的视图

Cell.accessoryView = UITableViewCellAccessoryCheckmark;

cell.accessoryView = [UIbutton alloc]init];(可以在右边自定义控件可以放一个按钮或者一个开关)

 


 


注意:以上cell的属性包含了4个属性

Cell的重用原理

iOS设备的内存有限,如果用UITableView显示成千上万条数据,就需要成千上万个UITableViewCell对象的话,那将会耗尽iOS设备的内存。要解决该问题,需要重用UITableViewCell对象

重用原理:当滚动列表时,部分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对象

Cell的重用代码

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

{

 

注意:重用机制是根据相同的标识符来重用cell,标识符不同的cell不能彼此重用

  1.定义一个cell的标识为ID

      static NSString *ID = @"mjcell";

    

     2.从缓存池中取出cell

      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    

     3.如果缓存池中没有cell

      if (cell == nil) {

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];

    }

    

     4.设置cell的属性...

    

      return cell;

}

 

方法2:注册

                                     

          另一中性能优化的写法:

          0.先确定cell的重用标识

          1.注册带重用标识的cell

          2.从缓存池中取是否有带重用标识的cell(如果没有,系统会根据注册自动创建一个相应的cell返回给我们)

          3.覆盖cell上面的数据

          说明:cell离开屏幕的时候,就会放到tableView的缓存池中,这时候缓存池才有数据

         

   

             3.0 先确定cell的重用标识:命名规范:cell类型+ID

            static NSString *ID = @"carID"; // static修饰局部变量,局部变量从执行后始终存在, 但不能被其它函数使用, 当再次进入该函数时, 将保存上次的结果。其它与局部变量一样。

            

            static BOOL isReged = NO;

             3.1 先注册带IDcell

            if (isReged == NO) {

warning registerCell需要注意的3,面试可能会问到

                     方法是伴随着UICollectionView出现的,也就是iOS6出现的

                     采用注册创建出来的cell,默认是Default样式,所以一般注册大部分都用在自定义cell的时候

                     需要注意的是 [tableView registerNib:<#(UINib *)#> forCellReuseIdentifier:<#(NSString *)#>] iOS5出现的

 编码规范:xib自定义cell一般用注册

                    [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ID];

                    isReged = YES;

                   

                }

            

             3.2 查看缓存池中是否有带重用标识的cell

             缓存池方法中封装了,如果缓存池中没有,就根据注册创建新的cell,然后返回给我们一个带IDcell

            UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

            

             3.3 覆盖cell上的数据

            XMGCar *car = self.cars[indexPath.row];

            

            cell.textLabel.text = [NSString...

                                                                  

             3.4返回cell

            return cell;

                                                                  }

# 方法3:storyboard

                  另一中性能优化的写法(storyboard):

                  0.先确定cell的重用标识

                  1.storyboard中的tableView中的cell的重用标志赋值

                  2.从缓存池中取是否有带重用标识的cell

                  (2.1 如果没有,系统会根据注册自动创建一个相应的cell返回给我们;

                  2.2 如果也没有注册过,系统会根据storyboard中写好的带重用标志的cell来自动创建,然后返回)

                  3.覆盖cell上面的数据

                  说明:cell离开屏幕的时候,就会放到tableView的缓存池中,这时候缓存池才有数据

 

 3.返回每行内容:该方法,只有当cell显示在屏幕上的时候才会调用,是一种懒加载的思想

                               

warning 如果有注册,就不会触发storyboard的创建新cell的机制.只有没有注册过,并且storyboard中没有标记相应cell 的时候,dequeueReusableCellWithIdentifier才会返回nil

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

        {

                 3.0 先确定cell的重用标识:命名规范:数据的模型+ID

                static NSString *ID = @"carID";  static修饰局部变量,局部变量只会分配一次内存地址

    

                 3.1 查看缓存池中是否有带重用标识的cell

                 缓存池方法中封装了,如果缓存池中没有,就根据注册创建新的cell,然后返回给我们一个带IDcell

                 后面还封装了一层,如果也没有注册呢,会根据storyboard中是否标记了在重用cell,来创建一个新的cell然后返回

                UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

     

                 3.3 覆盖cell上的数据

                XMGCar *car = self.cars[indexPath.row];

                cell.textLabel.text = [N...

                     return cell;

          }


     3.修改控件属性(一半在cell的创建方法中设置initWithStyle)

    cell.imageView.layer.cornerRadius = 22;  设置圆角为正方形边长一半(内切圆半径)

    cell.imageView.layer.masksToBounds = YES; 设置将位于imageView之下的layer都遮盖住(默认是NO)  等效代码是:cell.imageView.clipsToBounds

    

     设置字体以及文字颜色

    cell.textLabel.textColor = [UIColor brownColor];

    cell.detailTextLabel.font = [UIFont systemFontOfSize:12.0];

    cell.detailTextLabel.textColor = [UIColor grayColor];

    

     设置辅助视图

    cell.accessoryType = UITableViewCellAccessoryDetailButton;







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值