UITableView表格操作

时间:2023-09-23 15:29:19

UITableView【表格视图】

UITableView是表格视图,是UIScrollView的子类,非常重要。

一、表格视图常用属性

1、基本属性方法

创建一个tableView

//    UITableViewStylePlain, //扁平风格的

//    UITableViewStyleGrouped //跟系统设置风格是一样的   分组风格

UITableView *tableView = [[UITableView alloc]initWithFrame:self.view.frame style:UITableViewStyleGrouped];

表格的背景颜色

tableView.backgroundColor = [UIColor orangeColor];

如果根视图是导航视图控制器,则需要取消导航控制器对布局的影响

方法一:

//让导航条透明(原点坐标是从屏幕左上角开始的),scrollview(子类) 正常显示

self.automaticallyAdjustsScrollViewInsets = NO;

CGRect tableViewFrame = tableView.frame ;

tableViewFrame.origin.y += 64;

tableViewFrame.size.height -= 64;

tableView.frame = tableViewFrame;

方法二:

//取消导航视图控制器 对布局(第一个子视图是UIScrollview的子类)的影响

// 设置UIRectEdgeNone 之后,你发发现 self.view 零点是导航栏下边开始的

self.edgesForExtendedLayout = UIRectEdgeNone;

CGRect tableViewFrame = tableView.frame ;

tableViewFrame.size.height -= 64;

tableView.frame = tableViewFrame;

分割线的类型

UITableViewCellSeparatorStyleNone, 没有(一般情况下,做一些比较复杂cell 分割线是不显示,自己可以定制一条分割线)

UITableViewCellSeparatorStyleSingleLine,细线

UITableViewCellSeparatorStyleSingleLineEtched 没有

tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;

分割线颜色

tableView.separatorColor = [UIColor redColor];

设置分割线边界的

tableView.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0);

tableview 的头视图 和 尾视图   是一个UIView类型的

tableView.tableHeaderView

tableView.tableFooterView

2、数据代理方法

UITableViewDataSource 数据源协议,告诉tableView 要显示多少行和每一行要显示内容

设置代理

tableView.dataSource = self;

代理方法必须实现的方法  (行数和内容)

//设置第section组的行数

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

return   [self.dataSource[section] count];

}

//设置cell 内容(行内容)

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

//创建一个cell

//第一个参数 cell的风格

//第二个参数 唯一标示符 用来复用cell的,怎么复用呢,只创建比我们能看到屏幕上cell 多一点,每当我们下滑动的时候,会多的cell 拿过来用。系统会创建一个复用的队列,每当需要创建cell的时候,会先去队列里面找有没有可用的cell(cellID是一样的),如果有可用的,就拿过来用,如果没有可用的cell,就直接创建一个。

//先检测复用队列,有没有可以用cell

static NSString *cellID = @"cellID";

//检测对应id 有没有对应的可用cell

UITableViewCell *reuseCell = [tableView dequeueReusableCellWithIdentifier:cellID];

if (reuseCell == nil) {

不存在可以复用cell,就去创建一个

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

}

cell自带了一个label 和imageView

cell的类型:

UITableViewCellStyleDefault   有两个label

UITableViewCellStyleValue1,(系统的设置风格)

UITableViewCellStyleValue2,(跟系统联系人的风格相似)(图片不会显示)

UITableViewCellStyleSubtitle

NSString *name =  self.dataSource[indexPath.section][indexPath.row];

cell.textLabel.text = name;

//设置图片

cell.imageView.image = [UIImage imageNamed:@"2"];

//详细信息label

cell.detailTextLabel.text = @"详细信息";

//cell的内容视图(放自定义控件)

cell.contentView.backgroundColor = [UIColor cyanColor];

//指示附加视图

cell.accessoryType = UITableViewCellAccessoryDetailButton;

//自己定制附加视图

cell.accessoryView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"3"]];

附件视图被点中会调用协议方法

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

//点击cell之后的风格

//    UITableViewCellSelectionStyleNone,

//    UITableViewCellSelectionStyleBlue,

//    UITableViewCellSelectionStyleGray,

//    UITableViewCellSelectionStyleDefault

cell.selectionStyle = UITableViewCellSelectionStyleGray;

//设置选中的背景视图

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

selectedView.backgroundColor = [UIColor blueColor];

cell.selectedBackgroundView = selectedView;

return cell;

}

//设置tableview 有多少组

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

return self.dataSource.count;

}

//分组的 index title

- (nullable NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView {

return @[@"a",@"b",@"b",@"c",@"c"];

}

//改变 点击index title 所 跳到的组

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {

if ([title isEqualToString:@"a"]) {

return 4;

}

return index;

}

3、本身代理方法

设置行、头视图,尾视图的高

设置头视图和尾视图    返回值UIView

设置头视图和尾视图的title  返回NSString

选中某一行

////设置组头

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

UIView *headerSectionView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)];

headerSectionView.backgroundColor = [UIColor yellowColor];

return headerSectionView;

}

////设置组尾视图

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

UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)];

view.backgroundColor = [UIColor greenColor];

return view;

}

////设置组头高度

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

return 100;

}

////组尾高度

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

return 100;

}

//设置组头title //粘性表头  tableview 的风格 必须是plain,组头组尾视图不能设置,系统默认的头尾视图。

- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;

- (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;

//选了某一行

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

//可以选中进去之后,在出来,cell 就不被选中

[tableView deselectRowAtIndexPath:indexPath animated:YES];

将选中的行的信息在另一个视图显示

DetailViewController *dvc = [[DetailViewController alloc]init];

//点击的那一行的 名字

NSString *name =  self.dataSource [indexPath.section][indexPath.row];

dvc.name = name;

[self.navigationController pushViewController:dvc animated:YES];

}

代理

tableView.delegate  = self;

// tableview 是继承于UIScrollview·的,所以UIscrollView的协议方法,tableView都能用

#pragma mark - UIScrollViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {

NSLog(@"scrollViewDidScroll");

}

二、表格视图的基本操作

1、      为了方便操作,创建了表格的基类,在基类中实现以后必须要用的方法(行,内容)和属型,必须在.h中声明属性和非类方法(后续需要不断使用的方法)

@property (nonatomic, strong) UITableView *tableView;

@property (nonatomic, strong) NSMutableArray *dataSource;

/**

*  创建数据源 子类取实现 需要重写

*/

- (void)createDataSource;

2、操作表格时需实现协议中的方法 对表格  提交编辑和 设置编辑(多行删除除外)

****************************************************************添加一行 AddCellViewController

(1)  首先,重写数据源    数据源单独作为一个类,创建多种数据源

- (void)createDataSource {

self.dataSource = [DataSourceStore createOPDataSource];

}

(2)根据数据源中数据存储的形式重写类方法cell

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

UITableViewCell *reusableCell = [super tableView:tableView cellForRowAtIndexPath:indexPath];

reusableCell.textLabel.text = [NSString stringWithFormat:@"重写%@",self.dataSource[indexPath.row]]  ;

return reusableCell;

}

(3)编辑表格

//编辑的风格

//    UITableViewCellEditingStyleNone,

//    UITableViewCellEditingStyleDelete,

//    UITableViewCellEditingStyleInsert

// 提交编辑

//类方法

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

if (editingStyle == UITableViewCellEditingStyleInsert) {

//首先要在数据源添加一个数据

[self.dataSource insertObject:@"添加的" atIndex:indexPath.row];

//刷新全部的数据

//[self.tableView reloadData];

//插入一行 刷新一行

[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

}

else if (editingStyle == UITableViewCellEditingStyleDelete){

NSLog(@"删除");

}

}

//设置编辑风格

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

return UITableViewCellEditingStyleInsert;

}

****************************************************************删除一行  RemoveViewController

(1)  首先,重写数据源

(2 )编辑表格

//提交编辑

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

if (editingStyle == UITableViewCellEditingStyleDelete) {

//先删除数据源的某个元素

[self.dataSource removeObjectAtIndex:indexPath.row];

[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

}

}

//设置编辑类型

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

return UITableViewCellEditingStyleDelete;

}

//iOS8的新属性,自定义左滑cell按钮

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

//行动作

//    UITableViewRowActionStyleDefault = 0,

//    UITableViewRowActionStyleDestructive = UITableViewRowActionStyleDefault,

//    UITableViewRowActionStyleNormal

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

NSLog(@"点击置顶按钮");

}];

UITableViewRowAction *action2 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"删除" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {

NSLog(@"点击删除按钮");

}];

return @[action1,action2];

}

**********************************************************************删除多行不需要编辑表格和提交编辑,需要直接重写item“编辑”的触发事件

(1)  首先,重写数据源

(2 )重写导航栏的“编辑”item的触发事件

//设置编辑

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

return UITableViewCellEditingStyleDelete | UITableViewCellEditingStyleInsert;

}

//用两个协议方法来记录选中和撤销

//撤销选中行

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

}

//选中行

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

//只有是编辑模式的时候我们才去几乎选中的行

if (tableView.isEditing) {

}

//有一个专门记录选中的行数

//  tableView.indexPathsForSelectedRows;

//  NSLog(@"%ld",tableView.indexPathsForSelectedRows.count);

}

- (void)itemPressed:(UIBarButtonItem*)item {

NSLog(@"强制重写");

if (self.tableView.isEditing) {

//在这里处理多选删除

//先删除数据源

//多选删除的时候必须要倒序删除

//1、先把数组里边的元素排序

NSArray *resultArray = [self.tableView.indexPathsForSelectedRows sortedArrayUsingSelector:@selector(compare:)];

//按照数组里边的内容 类型 compare: 方法进行排序,一般compare:都是从小到大排序

//逆序数组,首先逆序枚举,然后取出所有得元素

NSArray *reverseArray = [[resultArray reverseObjectEnumerator] allObjects];

for (NSIndexPath *indexpath in reverseArray) {

[self.dataSource removeObjectAtIndex:indexpath.row];

}

//刷新界面

[self.tableView deleteRowsAtIndexPaths:self.tableView.indexPathsForSelectedRows withRowAnimation:UITableViewRowAnimationAutomatic];

// self.tableView.editing = NO;

//带有动画效果

[self.tableView setEditing:NO animated:YES];

}

else {

//self.tableView.editing = YES;

[self.tableView setEditing:YES animated:YES];

}

}

***********************************************************************折叠FoldViewController

- (void)viewDidLoad {

[super viewDidLoad];

//初始化数组状态,设置section全是关闭

self.sectionsState = [NSMutableArray arrayWithObjects:@0,@0,@0,@0, nil];

// Do any additional setup after loading the view.

}

- (void)createDataSource {

self.dataSource = [DataSourceStore createFlodDataSource];

}

//两个重要的协议

//行数

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

NSNumber *state = self.sectionsState[section];

//如果是关闭的,返回0;

if (state.intValue == 0) {

return 0;

}

else{

//只要是打开的就返回数组里面的元素个数

return [self.dataSource[section] count];

}

}

//内容

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

static NSString *cellID = @"cellID";

UITableViewCell *reusableCell = [tableView dequeueReusableCellWithIdentifier:cellID];

if (reusableCell == nil) {

reusableCell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];

}

reusableCell.textLabel.text = self.dataSource[indexPath.section][indexPath.row];

return reusableCell;

}

//组数

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

return [self.dataSource count];

}

//设置组头

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

UIButton *headerView = [UIButton buttonWithType:UIButtonTypeSystem];

headerView.frame = CGRectMake(0, 0, self.view.frame.size.width, 44);

[headerView setTitle:@"我的好友" forState:UIControlStateNormal];

headerView.backgroundColor = [UIColor greenColor];

[headerView addTarget:self action:@selector(headerViewPressed:) forControlEvents:UIControlEventTouchUpInside];

headerView.tag = section + 100;

return headerView;

}

- (void)headerViewPressed:(UIButton*)sender {

NSInteger section = sender.tag - 100;

BOOL state = [self.sectionsState[section] boolValue];

//修改数据源

NSNumber *currentState = state?@0:@1;

//如果是关着的就设置现在的状态为开,反之一样

[self.sectionsState replaceObjectAtIndex:section withObject:currentState];

//刷新对应的section

[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationAutomatic];

//NSLog(@"点击了%ld头视图",section);

}

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

return 44.0;

}

****************************************************************** 移动  MoveViewController

(1)  首先,重写数据源

(2 )设置行可以移动

//让表格可以移动

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {

return YES;

}

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

return  UITableViewCellEditingStyleNone;

}

(3 )移动表格的行

//移动表格的协议方法

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {

//改变数据源

[self.dataSource exchangeObjectAtIndex:sourceIndexPath.row withObjectAtIndex:destinationIndexPath.row];

}

*******************************************************************搜索 SearchViewController

首先必须遵守的两个协议UISearchBarDelegate,UISearchDisplayDelegate

为了方便使用,设置三个属性

@property (nonatomic, strong) UISearchBar *searchBar;  搜索栏

@property (nonatomic, strong) UISearchDisplayController *searchDC; 显示搜索结果

@property (nonatomic, strong) NSMutableArray *resultArray;  存放搜索的结果

(1)首先,创建视图,将搜索栏添加到表格的   表头  并设置协议的代理

- (void)createView {

_searchBar = [[UISearchBar alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44.0)];

_searchBar.placeholder = @"请输入";

self.tableView.tableHeaderView = _searchBar;

_searchDC = [[UISearchDisplayController alloc]initWithSearchBar:_searchBar contentsController:self];

_searchDC.searchResultsDelegate = self;

_searchDC.searchResultsDataSource= self;

}

(2)创建数据源

(3)实现tableView必须实现的两个协议方法(重写行数和内容)

//行数

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

if (tableView == self.tableView) {

return [self.dataSource count];

}

else{

//说明是searchBar的tableView

//        //拿到搜索结果

//        //谓词搜索

//        //查询后面的字符串是否包含搜索内容

//        NSPredicate *pd = [NSPredicate predicateWithFormat:@"self contains[cd]%@",_searchBar.text];

//        //在我们的数据源查找

//        NSArray *array1 = [self.dataSource filteredArrayUsingPredicate:pd];

//        self.resultArray = [NSMutableArray arrayWithArray:array1];

//

//        return self.resultArray.count ;

//第二种方法  ios8以后才能用

self.resultArray = [NSMutableArray new];

for (NSString *item in self.dataSource) {

BOOL contains = [item containsString:_searchBar.text];

if (contains) {

//只要包含 就添加到结果里边

[_resultArray addObject:item];

}

}

return self.resultArray.count;

}

}

//搜索内容

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

static NSString *cellID = @"cellID";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];

if (cell == nil) {

cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];

}

if (tableView == self.tableView) {

cell.textLabel.text = self.dataSource[indexPath.row];

}

else {

//就是我们的searchBar的tableView视图

cell.textLabel.text = self.resultArray[indexPath.row];

}

return cell;

}