UITableView控件
UITableView有两种样式:grouped/plain 组/单行
UITableView需要⼀一个数据源(dataSource)来显示数据
UITableView会向数据源查询一共有多少行数据以及每⼀行显示什么数据等
没有设置数据源的UITableView只是个空壳
凡是遵守UITableViewDataSource协议的OC对象,都可以是UITableView的数据源
展示数据的过程:
(1)调用数据源的下面⽅法得知⼀一共有多少组数据
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
(2)调用数据源的下面⽅法得知每一组有多少行数据
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
(3)调⽤数据源的下⾯⽅法得知每⼀⾏显示什么内容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
(1)设置分割样式和边距(tableview.separatorStyle),这是个枚举类型
separatorInset
(2)设置分割线的颜色,可以直接使用系统给出的颜色,如果系统给定的颜色不能满足需求时,也可以自定义。
补充:颜色分为24位和32位的,如下
24bit颜色
R 8bit 0 ~ 255
G 8bit 0 ~ 255
B 8bit 0 ~ 255
32bit颜色
A 8bit 0 ~ 255(tou)
R 8bit
G 8bit
B 8bit
#ff ff ff 白色
#00 00 00 黑色
#ff 00 00 红色
#255 00 00
设置为自定义颜色的实例:tableview.separatorColor = [UIColorcolorWithRed:0/255.0green:255/255.0blue:0/255.0alpha:255/255.0];
//接收的参数是颜色的比例值
(3)设置顶部和底部视图
tableview.tableHeaderView //顶部
tableview.tableFooterView //底部
4)设置cell的高度
tableView.rowHeight // cell高度
5)每一组的头部、尾部高度
sectionHeaderHeight
sectionFooterHeight
6)背景颜色两个属性
backgroundView(优先级高)
backgroundColor(优先级低)
默认tableView设置颜色会被它上面cell挡住,可以设置cell的透明度
7)刷新数据
reloadData(整个tableView的数据)
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation
(刷新某一个组某一行的数据)
3,UITableViewCell的常用属性
UITableViewCell内部用一个contentView属性在contentview中默认有三个子视图:
第2个是UILabel(通过UITableViewCell的textLabel和detailTextLabel属性访问)
第3个是UIImageView(通过UITableViewCell的imageView属性访问)
UITableViewCell还有⼀个UITableViewCellStyle属性,⽤于决定使用contentView的哪些子视图,以及这些子视图在contentView中的位置
1)辅助视图
1)设置cell的辅助视图,设置cell.accessoryView(系统提供了枚举型,也可以自定义@父类指针指向子类对象);
2,设置cell的背景颜色两种属性
backgroundColor/ backgroundView
选中状态的颜色
selectedbackgroundView(color)
4 常用的数据源方法和代理方法
数据源方法:
代理方法:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
5,UITableViewCell的性能问题
问题:cell的工作:在程序执行的时候,能看到多少条,它就创建多少条数据,如果视图滚动那么再创建新显示的内容。(系统自动调用)。即当一个cell出现在视野范围内的时候,就会调用创建一个cell。这样
cell重用原理 :当滚动列表时,部分UITableViewCell会移出窗口,UITableView会将窗口外的UITableViewCell放入一个对象池中,等待重用。当UITableView要求dataSource返回 UITableViewCell时,dataSource会先查看这个对象池,如果池中有未使用的UITableViewCell,dataSource则会用新的数据来配置这个UITableViewCell,然后返回给 UITableView,重新显示到窗口中,从而避免创建新对象
注意点:对象池中也会有很多不同类型的 UITableViewCell,那么UITableView在重⽤用UITableViewCell时可能会得到错误类型的 UITableViewCell
解决方案:UITableViewCell有个NSString *reuseIdentifier属性,可以在初始化UITableViewCell的时候传入一个特定的字符串标识来设置reuseIdentifier(一般用UITableViewCell的类名)。当UITableView要求dataSource返回UITableViewCell时,先 通过一个字符串标识到对象池中查找对应类型的UITableViewCell对象,如果有,就重用,如果没有,就传入这个字符串标识来初始化⼀一个UITableViewCell对象。
缓存优化的思路:
(1)先去缓存池中查找是否有满足条件的cell,若有那就直接拿来
(2)若没有,就自己创建一个cell
(3)创建cell,并且设置一个唯一的标记(把属于“”的给盖个章)
(4)给cell设置数据
注意点:
定义变量用来保存重用标记的值,这里不推荐使用宏(#define来处理),因为该变量只在这个作用域的内部使用,且如果使用宏定义的话,定义和使用位置太分散,不利于阅读程序。由于其值不变,没有必要每次都开辟一次,所以用static定义为一个静态变量。
6,刷新数据的两个步骤:
1)修改模型
2)刷新表格数据(可以全部刷新,也可以刷新指定的行)
代码案例:
数据模型:
#import <Foundation/Foundation.h> @interface LLHeroList : NSObject @property (nonatomic, copy) NSString *icon; @property (nonatomic, copy) NSString *intro; @property (nonatomic, copy) NSString *name; - (instancetype)initWithDic:(NSDictionary *)dic; + (instancetype)heroListWithDic:(NSDictionary *)dic; + (NSMutableArray *)heroesList; @end
#import "LLHeroList.h" @implementation LLHeroList - (instancetype)initWithDic:(NSDictionary *)dic { if (self = [super init]) { [self setValuesForKeysWithDictionary:dic]; } return self; } + (instancetype)heroListWithDic:(NSDictionary *)dic { return [[self alloc] initWithDic:dic]; } + (NSMutableArray *)heroesList { NSString *path = [[NSBundle mainBundle] pathForResource:@"heros" ofType:@"plist"]; NSArray *dicArr = [NSArray arrayWithContentsOfFile:path]; NSMutableArray *tmpArr = [[NSMutableArray alloc] initWithCapacity:dicArr.count]; for (NSDictionary *dic in dicArr) { LLHeroList *hero = [LLHeroList heroListWithDic:dic]; [tmpArr addObject:hero]; } return tmpArr; } @end
controller:
#import "ViewController.h" #import "LLHeroList.h" @interface ViewController ()<UITableViewDataSource, UITableViewDelegate, UIAlertViewDelegate, UIActionSheetDelegate> @property (nonatomic, strong) NSMutableArray *heroes; @property (nonatomic, weak) UITableView *tableView; @end @implementation ViewController - (NSMutableArray *)heroes { if (!_heroes) { _heroes = [LLHeroList heroesList]; } return _heroes; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self loadTableView]; } - (void)loadTableView { UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain]; [self.view addSubview:tableView]; self.tableView = tableView; self.tableView.dataSource = self; self.tableView.rowHeight = 60; // tableView的代理 self.tableView.delegate = self; // tableView分割线颜色设置: self.tableView.separatorColor = [UIColor colorWithRed:0/255.0 green:255/255.0 blue:0/255.0 alpha:1]; // 设置分割线的内边距 self.tableView.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0); } #pragma mark - 数据源方法 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.heroes.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *ID = @"hero"; UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:ID]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; } LLHeroList *hero = self.heroes[indexPath.row]; cell.imageView.image = [UIImage imageNamed:hero.icon]; cell.textLabel.text = hero.name; cell.detailTextLabel.text = hero.intro; // 给cell添加辅助按钮 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; // 给cell添加背景图片 cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"buttonorange"]]; // 设置cell选中的颜色 cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"buttonred"]]; return cell; } #pragma mark - tableView的代理方法 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // // 1,创建一个alertView对象 // UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"英雄展示" message:nil delegate:self cancelButtonTitle:@"cancle" otherButtonTitles:@"ok", nil]; // // // 2,设置alertView的样式(3中样式) // alertView.alertViewStyle = UIAlertViewStylePlainTextInput; // // // 3,设置alertView文本输入框展示的内容 // [alertView textFieldAtIndex:0].text = [self.heroes[indexPath.row] name]; // // // 4,给alertView的代理方法传递当前选中行的行号 // alertView.tag = indexPath.row; // [alertView show]; UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"英雄展示" delegate:self cancelButtonTitle:@"cancel" destructiveButtonTitle:@"删除英雄" otherButtonTitles:@"ok" ,nil]; sheet.tag = indexPath.row; [sheet showInView:[[UIView alloc] init]]; } #pragma mark - alertView的代理方法 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { if (buttonIndex == 0) return; // 修改数据模型 LLHeroList *hero = self.heroes[alertView.tag]; hero.name = [alertView textFieldAtIndex:0].text; // 刷新表格 // // 全部刷新 // [self.tableView reloadData]; // 局部刷新 NSIndexPath *indexPath = [NSIndexPath indexPathForRow:alertView.tag inSection:0]; [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationBottom]; } #pragma mark - actionSheet代理方法 - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { if (buttonIndex == 0) { [self.heroes removeObjectAtIndex:actionSheet.tag]; [self.tableView reloadData]; } } @end
效果: