UI基础之tableView
Posted 忆缘晨风
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UI基础之tableView相关的知识,希望对你有一定的参考价值。
---恢复内容开始---
1.Cell的重用机制:
如下图所示:我们在写tableview的数据源方法的时候,在第三个方法中通常会碰到定义重用cell的三步骤
#pragma mark -- 数据源方法 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return self.dataArray.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ //1.定义重用标识符 static NSString *identifier = @"cellID"; //2.根据重用标识符去缓存区中查找重用cell UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; //3.判断是否有重用cell if (!cell) { cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier]; } return cell; }
cell重用机制:如上图:最开始的时候,tableview是没有任何cell,此时缓存区也没有重用的cell,数据源方法会走(
//2.根据重用标识符去缓存区中查找重用cell
)这个方法,显然是找不到的,那么继续走第三个方法,创建一个cell,仔细看这个方法,是带有重用标识符的,这个方法做了什么呢?
如下图:这个方法给创建好的cell一个重用标识符,然后再走(
cellForRowAtIndexPath
)方法,继续创建,直到创建完成,当我们上下拖动时,就会调用缓存区中的重用cell,从而实现cell的重用.
2.cell也可以用加载xib
// // ViewController.m // 04-原型cell // // Created by apple on 16/7/17. // Copyright © 2016年 itcast. All rights reserved. // #import "ViewController.h" @interface ViewController ()<UITableViewDataSource> @end @implementation ViewController #pragma mark --UITableViewDataSource //返回组 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return 1; } //返回行 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return 10; } //返回cell - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ //1. 定义重用标识 static NSString *reuseId = @"cell"; //2. 获取重用cell UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId]; //3. 判断cell是否存在 if (!cell) { //4. 创建cell NSLog(@"创建新的cell %ld",indexPath.row); cell = [[[NSBundle mainBundle]loadNibNamed:@"MyCell" owner:nil options:nil]lastObject]; } //5. 设置属性 // cell.textLabel.text = [NSString stringWithFormat:@"当前 %ld 组 %ld行",indexPath.section,indexPath.row]; //6. 返回cell return cell; } @end
通过xib加载cell,其实也就是自定义的cell,之所以引入这种加载方式,其实就是因为系统的cell满足不了我们要的需求.
3.原型cell的小结:
首先:什么是原型cell?为什么引入?
原型cell,其实呢,就是在storyboard中,拉入一个UItableviewController,每一个UItableviewController都自带cell,这个cell就是原型cell
// // ViewController.m // 04-原型cell // // Created by apple on 16/7/17. // Copyright © 2016年 itcast. All rights reserved. // #import "ViewController.h" @interface ViewController ()<UITableViewDataSource> @end @implementation ViewController #pragma mark --UITableViewDataSource //返回组 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return 1; } //返回行 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return 10; } //返回cell - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ //1. 定义重用标识 static NSString *reuseId = @"cell"; //2. 获取重用cell // 原型cell--> 只要直接在对应storyboard中,对应的UITableViewCell上设置一个重用的标识,就可以直接加载 // 原型cell的加载,不会走第四步创建 // 虽然第四步创建,说的是如果没有重用的cell,就创建新的cell -->虽然原型cell不会走第四步新创建的过程 // 但是绝对不代表说cell 就不会创建了-->只不过它的创建由系统完成 // // 当使用原型cell的时候,系统会先从UITableView中获取是否有重用的cell,如果没有系统自己去完成创建,如果有就直接使用 // 而创建的方式,就是根据判断对应storyboard中,是否有一个cell的标识属性,跟获取重用的标识属性一致 // UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId]; // unable to dequeue a cell with identifier cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard\' //forIndexPath 多了这样一个参数-->参数的用处,首先indexPath无论有任何值,都没有任何意义,它在这里的唯一作用,就是用来判断,是否是从原型cell中进行创建 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId forIndexPath:indexPath]; //3. 判断cell是否存在 // if (!cell) { // //4. 创建cell // NSLog(@"创建新的cell %ld",indexPath.row); // cell = [[[NSBundle mainBundle]loadNibNamed:@"MyCell" owner:nil options:nil]lastObject]; // } //5. 设置属性 // cell.textLabel.text = [NSString stringWithFormat:@"当前 %ld 组 %ld行",indexPath.section,indexPath.row]; //6. 返回cell return cell; } @end
原型cell:直接从SB 中加载的,这里面有一些注意点:
区别两个方法:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId forIndexPath:indexPath];
这两个方法都是通过重用标识符去查找是否有重用的cell,都能起到cell重用的作用,但第二个方法中多了个forIndexPath参数,
作用是只会加载原型cell,如果标识符不匹配,直接报错(crash掉),但是第一个方法不会,他会找标识符,如果原型cell标识符不匹配,
如上例所示,他会找xib中的标识符,如果xib中的标识符匹配,就会加载xib,如果SB(原型cell)和xib中标识符都匹配,那么优先加载SB,
其实:只要原型cell可以加载,那么tableview就不会加载其他的(如xib)cell了.
那么,引入原型cell的好处是什么呢?
//返回cell - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ //1. 定义重用标识 NSString *reuseId = @"cell"; //2. 获取重用cell的时候,使用一个带indexPath参数的方法 // 通过这个标识,如果加载的不是storyboard中的原型cell就会报错 // 使用原型cell的好处: // 1. 代码少写了 // 2. 系统在加载cell,cell的高度,系统会自动判断进行自动的设定,可以不需要通过代码的方式进行设置 会根据自己拉多大自动设置行高 // 3. 扩充:当界面中cell的样式不一样的时候,可以简单通过一个标识进行区分,不需要写太多的代码 UITableViewCell *cell; if (indexPath.row < 3) { cell = [tableView dequeueReusableCellWithIdentifier:reuseId forIndexPath:indexPath]; }else{ cell = [tableView dequeueReusableCellWithIdentifier:@"cell1" forIndexPath:indexPath]; } //3. 设置属性 // cell.textLabel.text = [NSString stringWithFormat:@"当前 %ld 组 %ld 行",indexPath.section,indexPath.row]; //4. 返回cell return cell;
4.静态cell:
静态cell只能在UItableviewController中使用,好处是不需要写数据源方法,也不需要写代理方法,但原型cell不写数据源方法和代理是不能加载出界面的.
记住:这个image是静态cell自带的,所以可以直接设置,会自动选好位置,不用自己再拖一个新的imageView进去,所以很牛逼!
注意点:xib使用注意事项
/** * 这个方法可以当成是 viewDidLoad方法去看到 * 界面加载就会调用-->唯一的区别在awakeFromNib 从nib中唤醒 * 这个方法,只有从xib中加载控件的时候才会调用 * 只在初始化的时候调用 * 如果不是在xib中创建,那么就不会调用 * 以后用的也不是很多<但是做个记忆,一旦有需求,从xib中加载必须做什么事情的时候 */ - (void)awakeFromNib { // NSLog(@"从xib中加载控件"); } /** * 设置点击的状态 * * @param selected 是否允许保持点击的状态 */ - (void)setSelected:(BOOL)selected animated:(BOOL)animated { NSLog(@"被点击了"); [super setSelected:selected animated:animated]; // Configure the view for the selected state }
以上是关于UI基础之tableView的主要内容,如果未能解决你的问题,请参考以下文章
我们可以在活动 xml 中编写 UI 以及在片段 xm 中编写 UI 吗?