UITableView相关知识点

时间:2022-04-11 12:25:02
//*****UITableView相关知识点*****//

  1 #import "ViewController.h"

 // step1 要实现UITableViewDataSource协议,因为tableView不存储数据
@interface ViewController () <UITableViewDataSource, UITableViewDelegate> // step0 准备要显示的数据
@property(nonatomic,strong) NSMutableArray *dataArrM; @property(nonatomic,strong) UITableView *myTable; // 这个数组保存着每个分组的折叠状态
@property(nonatomic,strong) NSMutableArray *sectionShowArrM; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
[self myTable]; // 设置导航条
[self setNavigation ];
} -(void)setNavigation{ UIBarButtonItem *rightItem = [[UIBarButtonItem alloc]initWithTitle:@"Edit" style:UIBarButtonItemStylePlain target:self action:@selector(tableEdit:)]; self.navigationItem.rightBarButtonItem = rightItem;
}
// 点击导航右侧编辑按钮时,让表格可编辑
-(void)tableEdit:(UIBarButtonItem *) btnItem{ if (self.myTable.editing == NO ) { // 没有处于编辑状态,导航按钮文字为“Edit”
// 点击“编辑”文字,让表格处于编辑状态,并把按钮的文字修改为“Done"
self.myTable.editing = YES;
btnItem.title = @"Done";
// 创建一个新删除按钮
UIBarButtonItem *deleteBtn = [[UIBarButtonItem alloc]initWithTitle:@"Delete" style:UIBarButtonItemStylePlain target:self action:@selector(DeleteAllSeleted )]; self.navigationItem.rightBarButtonItems = @[btnItem, deleteBtn]; }else{
// 编辑状态下,点击”Done"按钮,取消表格的编辑状态,修改导航按钮文字为"Edit"
self.myTable.editing = NO;
btnItem.title = @"Edit" ;
self.navigationItem.rightBarButtonItems = @[btnItem];
} } // 删除选中的所有行
-(void)DeleteAllSeleted{
// 获取你选中的所有行
NSArray *selectedIndexPaths = self.myTable.indexPathsForSelectedRows;
// 删除数据源
// for (NSIndexPath *indexPath in selectedIndexPaths ) {
// // 0 1 2 3 4 5 6 7 8
// // 1 2 3 4 5 6 7 8
// // 1 3 4 5 6 7 8
// // 1 3 5 6 7 8
// // 0 1 2
// [self.dataArrM[indexPath.section] removeObjectAtIndex:indexPath.row];
// }
// 需要注意的是,一起删除数组中多个元素的时候,需要从数组的大索引值依次向小索引值删除
for (long i = selectedIndexPaths.count - ; i >= ; i-- ) {
NSIndexPath *indexPath = selectedIndexPaths[i];
[self.dataArrM[indexPath.section] removeObjectAtIndex:indexPath.row];
}
// 在表格中删除单元格
[self.myTable deleteRowsAtIndexPaths:selectedIndexPaths withRowAnimation:UITableViewRowAnimationAutomatic]; for (int i = ; i < self.dataArrM.count; i++ ) {
NSMutableArray *arr = self.dataArrM[i];
for (int j = ; j < arr.count ; j++ ) {
NSLog(@"%@", arr[j]);
}
}
} #pragma mark - tableView 的懒加载
// step2 在当前视图中添加tableView
-(UITableView *)myTable{
if ( !_myTable) {
_myTable =[[ UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStyleGrouped]; // _myTable = [[UITableView alloc]initWithFrame:CGRectMake(0, 64, self.view.bounds.size.width, self.view.bounds.size.height - 64 ) style:UITableViewStyleGrouped];
[self.view addSubview:_myTable ]; // step3 指定数据源代理, tableview的数据由当前控制器提供
_myTable.dataSource = self; //*********千万别忘记**********
_myTable.delegate = self; //*********千万别忘记********** // 设置表格的footerView
UIView *footerView = [[UIView alloc]initWithFrame:CGRectMake(, , _myTable.frame.size.width, )];
footerView.backgroundColor = [UIColor redColor];
_myTable.tableFooterView = footerView; // 设置表格允许多选
_myTable.allowsMultipleSelection = YES;
_myTable.allowsSelectionDuringEditing = YES;
_myTable.allowsMultipleSelectionDuringEditing = YES;
}
return _myTable;
} #pragma mark - 数组懒加载
-(NSMutableArray *)dataArrM{
if ( !_dataArrM ) {
_dataArrM = [NSMutableArray array];
for (int i = ; i < ; i++ ) {
NSMutableArray *sectionArrM = [NSMutableArray array];
for (int j = ; j < ; j++ ) {
NSString *str = [NSString stringWithFormat:@"第%d组,第%d行", i ,j ];
[sectionArrM addObject:str];
} [_dataArrM addObject:sectionArrM];
}
}
return _dataArrM;
} #pragma mark - 分组是否折叠数据的懒加载
-(NSMutableArray *)sectionShowArrM{
if (!_sectionShowArrM ) {
_sectionShowArrM = [NSMutableArray array];
for (int i = ; i < self.dataArrM.count ; i++ ) {
[_sectionShowArrM addObject:@NO]; // 默认起始状态为收起
}
}
return _sectionShowArrM;
} // step4 实现UITableViewDataSource协议方法
#pragma mark - UITableViewDataSource
// 返回有多少分组
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return self.dataArrM.count;
}
// 指定每个分组有多少行,返回0行表示该分组不显示单元格
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if ([self.sectionShowArrM[section] boolValue] == YES) {
// 如果sectionShowArrM数组中保存当前分组的状态是YES,为展开状态,返回数组元素的个数
return [self.dataArrM[section] count];
}else{
return ; // 收起状态
} }
// 指定要显示的单元格
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// 注册单元格类,并指定重用标识
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cellID"];
// 从tableView中找一个可重用的单元格,如果没有的话,系统会自动创建一个新的单元格
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellID" forIndexPath:indexPath];
// 指定单元格要显示的内容
cell.textLabel .text = self.dataArrM[indexPath.section][indexPath.row]; //返回单元格
return cell;
}
// 每个分组的头标题
- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ return [NSString stringWithFormat:@"第%ld组的头", section];
}
// 每个分组尾部的标题
- (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{
return [NSString stringWithFormat:@"第%ld组的尾部", section]; } // 指示是否允许编辑,具体的删除和插入操作由其他协议方法实现
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
return YES;
} // 指示表格中的行是否可以移动
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{
return YES;
} // 返回组索引的标题
- (nullable NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView{
NSMutableArray *sectionTitles = [NSMutableArray array];
for (int i = ; i < self.dataArrM.count ; i++ ) {
[sectionTitles addObject: [NSString stringWithFormat:@"%d组", i ]];
}
return sectionTitles;
} //- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index{
// if (index == 2 ) {
// return 0;
// }else {
// return index;
// }
//} // 提交单元格的编辑
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// 在数据源数组中删除相应的数据
[self.dataArrM[indexPath.section] removeObjectAtIndex:indexPath.row];
// 刷新表格
[self.myTable deleteRowsAtIndexPaths:@[indexPath ] withRowAnimation:UITableViewRowAnimationAutomatic];
}else if ( editingStyle == UITableViewCellEditingStyleInsert){
// 在数据源数组中插入数据
[self. dataArrM[indexPath.section] insertObject:@"新插入的行" atIndex:indexPath.row ];
// 刷新单元格
[self.myTable insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
} }
// 在该方法中一般实现数据源的交换
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
// 取出要移动行的内容
NSString *row = self.dataArrM[sourceIndexPath.section][sourceIndexPath.row];
// 在数据源中删除要移动的行
[self.dataArrM[sourceIndexPath.section] removeObjectAtIndex:sourceIndexPath.row];
// 在目的地插入要移动的行数据
[self.dataArrM[destinationIndexPath.section] insertObject:row atIndex:destinationIndexPath.row];
} #pragma mark - UITableViewDelegate
// 将要显示每个分组的footer的时候调用
- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section{ // if (section < self.dataArrM.count - 1 ) {
// return;
// }
//
// //获取更多数据
// NSMutableArray *addRowsArrM = [NSMutableArray array];
// for (int i = 0 ; i < 10 ; i++ ) {
// NSString *addRow = [NSString stringWithFormat:@"新添加的第%d行", i ];
// [addRowsArrM addObject:addRow];
// }
// [self.dataArrM addObject:addRowsArrM];
// //刷新表格
// NSIndexSet *indexSet = [[NSIndexSet alloc]initWithIndex:section];
// [self.myTable reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];
} // 返回第一行的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return ;
}
// 返回每个分组头部的高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
return ;
}
// 返回每个分组尾部的高度
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
return ;
} // 返回每个分组头部视图,如果实现了这个协议,tableView:titileForHeaderInSection协议方法不再起作用
- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
UIButton *headerBtn = [[UIButton alloc]initWithFrame:CGRectMake(, , tableView.frame.size.width, )];
[headerBtn setTitle:[NSString stringWithFormat: @"这是第%ld组的头部", section] forState:UIControlStateNormal] ;
headerBtn.titleLabel.textAlignment = NSTextAlignmentCenter;
headerBtn.backgroundColor = [UIColor orangeColor]; // [headerBtn setImage:[UIImage imageNamed:@"icon_back_highlighted"] forState:UIControlStateNormal];
UIImageView *btnImg = [[UIImageView alloc]initWithFrame:CGRectMake(, , , headerBtn.frame.size.height)];
btnImg.contentMode = UIViewContentModeScaleAspectFit;
btnImg.image = [UIImage imageNamed:@"icon_back_highlighted"];
[headerBtn addSubview:btnImg]; // 根据当前分组是否折叠来确定图标的旋转
BOOL isShow = [self.sectionShowArrM[section] boolValue];
if (isShow == YES) {
btnImg.transform = CGAffineTransformRotate(btnImg.transform, -M_PI_2);
}else{
btnImg.transform = CGAffineTransformIdentity;
} headerBtn.tag = + section;
// 添加事件
[headerBtn addTarget:self action:@selector(showSection: ) forControlEvents:UIControlEventTouchUpInside]; return headerBtn;
}
-(void)showSection:(UIButton *)button{
long sectionIndex = button.tag - ;
// 先获取当前分组的折叠状态
BOOL isShow = [self.sectionShowArrM[sectionIndex] boolValue];
if (isShow == NO ) { // 如果收起状态,点一下后,修改为展开状态
self.sectionShowArrM[sectionIndex] = @YES;
}else { // 展开状态
self.sectionShowArrM[sectionIndex] = @NO;
}
// 刷新当前分组
NSIndexSet *indexSet = [[NSIndexSet alloc] initWithIndex:sectionIndex];
[self.myTable reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic]; // 让分组头部左侧的图标旋转,这块代码放在这儿不合适,表格刷新后,图标会复位
// 获取当前按钮中的箭头
// UIImageView *btnImg;
// for (UIView *subView in button.subviews) {
// if ([subView isKindOfClass:[UIImageView class]]) {
// btnImg = (UIImageView *)subView;
// break;
// }
// }
//
// btnImg.transform = CGAffineTransformRotate(btnImg.transform , -M_PI_2);
} // 返回每个分组尾部视图
// - (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
//
// } // 返回单元格右侧的辅助按钮的类型
- (UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellAccessoryDisclosureIndicator;
}
// 当单元格右侧的辅助视图是一个按钮,当点击该按钮时,执行该协议方法
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{
NSLog(@"detailButton be tapped");
} // 指示是否允许高亮显示选中的行
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath{
return YES;
} // 选中某行时执行
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(@"selected: %ld, row:%ld", indexPath.section, indexPath.row);
}
// 取消选中时执行,这个方法常在表格允许多选时调用执行
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(@"Deselected: %ld, row:%ld", indexPath.section, indexPath.row);
} // 返回编辑时,是删除单元格还是插入单元格,要真正的实现删除或者插入操作,必须实现tableView:commitEditingStyle:forRowAtIndexPath:这个协议方法
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewCellEditingStyleInsert;
} // 单元格的缩进
- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath{
if(indexPath.row % == ){
return ;
}else{
return ;
}
} @end

UITableView相关知识点

UITableView相关知识点的更多相关文章

  1. Android开发涉及有点概念&amp&semi;相关知识点(待写)

    前言,承接之前的 IOS开发涉及有点概念&相关知识点,这次归纳的是Android开发相关,好废话不说了.. 先声明下,Android开发涉及概念比IOS杂很多,可能有很多都题不到的.. 首先由 ...

  2. IOS开发涉及有点概念&amp&semi;相关知识点

    前言,IOS是基于UNIX的,用C/C+/OC直通系统底层,不想android有个jvm. 首先还是系统架构的分层架构 1.核心操作系统层 Core OS,就是内存管理.文件系统.电源管理等 2.核心 ...

  3. IOS之UI--小实例项目--添加商品和商品名(使用xib文件终结版) &plus; xib相关知识点总结

    添加商品和商品名小项目(使用xib文件终结版) 小贴士:博文末尾有项目源码在百度云备份的下载链接. xib相关知识点总结 01-基本使用 一开始使用xib的时候,如果要使用自定义view的代码,就需要 ...

  4. 学习记录013-NFS相关知识点

    一.NFS相关知识点 1.NFS常用的路径/etc/exports NFS服务主配置文件,配置NFS具体共享服务的地点/usr/sbin/exportfs NFS服务的管理命令,exportfs -a ...

  5. TCP&sol;IP 相关知识点与面试题集

    第一部分:TCP/IP相关知识点 对TCP/IP的整体认 链路层知识点 IP层知识点 运输层知识点 应用层知识点 (这些知识点都可以参考:http://www.cnblogs.com/newwy/p/ ...

  6. Python开发一个csv比较功能相关知识点汇总及demo

    Python 2.7 csv.reader(csvfile, dialect='excel', **fmtparams)的一个坑:csvfile被csv.reader生成的iterator,在遍历每二 ...

  7. Caffe学习系列(二)Caffe代码结构梳理,及相关知识点归纳

    前言: 通过检索论文.书籍.博客,继续学习Caffe,千里之行始于足下,继续努力.将自己学到的一些东西记录下来,方便日后的整理. 正文: 1.代码结构梳理 在终端下运行如下命令,可以查看caffe代码 ...

  8. php正则相关知识点

    关于正则,其实简单就是搜索和匹配.php,java,python等都是支持正则的,php正则兼容perl.好多同学觉得正则比较难,比较抽象,其实正则是非常简单的,主要是一个熟悉和反复练习的结果,还有一 ...

  9. MySQL自增列(AUTO&lowbar;INCREMENT)相关知识点总结

      MySQL的自增列(AUTO_INCREMENT)和其它数据库的自增列对比,有很多特性和不同点(甚至不同存储引擎.不同版本也有一些不同的特性),让人感觉有点稍微复杂.下面我们从一些测试开始,来认识 ...

随机推荐

  1. WinForm最小化到托盘以及托盘右键菜单

    首先,先拖一个NotifyIcon到主窗体,然后设置NotifyIcon的图标,不然等下最小化后,都找不到那个程序了,还有那个Text也是,不写名字,就默认是NotifyIcon了..如下图: 然后双 ...

  2. 十五天精通WCF——第十三天 用WCF来玩Rest

    在我们玩wcf的时候,都会潜意识的觉得wcf就是通过soap协议交换消息的,并且可以在basic,tcp,msmq等等绑定中任意切换, 牛逼的一塌糊涂,但是呢,如果说哪一天wcf不再使用soap协议, ...

  3. IE input file隐藏不能上传文件解决方法

    当大神们都在探讨更深层次的问题时,我还在这里转载发些肤浅的问题解决方案.罢了,为了和我一样笨的后来人. 问题: 上传文件时,用<input type="file" /> ...

  4. python之时间函数

    import time print(time.clock())print(time.process_time())print(time.time()) #返回当前系统时间戳print(time.cti ...

  5. BZOJ&lowbar;1036&lowbar;&lbrack;ZJOI2008&rsqb;&lowbar;树的统计Conut&lowbar;&lpar;树链剖分&rpar;

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1036 给出一棵树以及各点的权值,对数进行如下三种操作: 1.改变某一节点u的值为t; 2.求节 ...

  6. 21 RadioGroup ListFragment

    结构 MainActivity.java package com.qf.day21_radiogroupfragment_demo3; import java.util.ArrayList; impo ...

  7. VLC 用到的那些 YUV 格式

    YUV是视频应用中使用的一类像素格式.YUV实际上是所有“YUV”像素格式共有的颜色空间的名称. 与RGB格式(红 - 绿 - 蓝)相对应,YUV颜色用一个称为Y(相当于灰度)的“亮度”分量和两个“色 ...

  8. 利用webpack搭建的前端工程化环境

    随着webpack3.x的发布,其功能也越来越强大,很多的项目的编译打包工具也由gulp逐渐转移到webpack.最近因为项目重构考虑使用使用vue,同时想从原来的gulp切换到webpack,所以搭 ...

  9. 递归&amp&semi;栈帧空间

    递归函数: 自己调用自己的函数 def digui(n): print(n) if n > 0: digui(n-1) print(n) digui(5) 执行结果: 5 4 3 2 1 0 0 ...

  10. 使用Java语言开发微信公众平台(三)——被关注回复与关键词回复

    在上一篇文章中,我们实现了文本消息的接收与响应.可以在用户发送任何内容的时候,回复一段固定的文字.本章节中,我们将对上一章节的代码进行适当的完善,同时实现[被关注回复与关键词回复]功能. 一.微信可提 ...