1. //*****UITableView相关知识点*****//
  2.  
  3. 1 #import "ViewController.h"
  4.  
  5. // step1 要实现UITableViewDataSource协议,因为tableView不存储数据
  6. @interface ViewController () <UITableViewDataSource, UITableViewDelegate>
  7.  
  8. // step0 准备要显示的数据
  9. @property(nonatomic,strong) NSMutableArray *dataArrM;
  10.  
  11. @property(nonatomic,strong) UITableView *myTable;
  12.  
  13. // 这个数组保存着每个分组的折叠状态
  14. @property(nonatomic,strong) NSMutableArray *sectionShowArrM;
  15.  
  16. @end
  17.  
  18. @implementation ViewController
  19.  
  20. - (void)viewDidLoad {
  21. [super viewDidLoad];
  22. [self myTable];
  23.  
  24. // 设置导航条
  25. [self setNavigation ];
  26. }
  27.  
  28. -(void)setNavigation{
  29.  
  30. UIBarButtonItem *rightItem = [[UIBarButtonItem alloc]initWithTitle:@"Edit" style:UIBarButtonItemStylePlain target:self action:@selector(tableEdit:)];
  31.  
  32. self.navigationItem.rightBarButtonItem = rightItem;
  33. }
  34. // 点击导航右侧编辑按钮时,让表格可编辑
  35. -(void)tableEdit:(UIBarButtonItem *) btnItem{
  36.  
  37. if (self.myTable.editing == NO ) { // 没有处于编辑状态,导航按钮文字为“Edit”
  38. // 点击“编辑”文字,让表格处于编辑状态,并把按钮的文字修改为“Done"
  39. self.myTable.editing = YES;
  40. btnItem.title = @"Done";
  41. // 创建一个新删除按钮
  42. UIBarButtonItem *deleteBtn = [[UIBarButtonItem alloc]initWithTitle:@"Delete" style:UIBarButtonItemStylePlain target:self action:@selector(DeleteAllSeleted )];
  43.  
  44. self.navigationItem.rightBarButtonItems = @[btnItem, deleteBtn];
  45.  
  46. }else{
  47. // 编辑状态下,点击”Done"按钮,取消表格的编辑状态,修改导航按钮文字为"Edit"
  48. self.myTable.editing = NO;
  49. btnItem.title = @"Edit" ;
  50. self.navigationItem.rightBarButtonItems = @[btnItem];
  51. }
  52.  
  53. }
  54.  
  55. // 删除选中的所有行
  56. -(void)DeleteAllSeleted{
  57. // 获取你选中的所有行
  58. NSArray *selectedIndexPaths = self.myTable.indexPathsForSelectedRows;
  59. // 删除数据源
  60. // for (NSIndexPath *indexPath in selectedIndexPaths ) {
  61. // // 0 1 2 3 4 5 6 7 8
  62. // // 1 2 3 4 5 6 7 8
  63. // // 1 3 4 5 6 7 8
  64. // // 1 3 5 6 7 8
  65. // // 0 1 2
  66. // [self.dataArrM[indexPath.section] removeObjectAtIndex:indexPath.row];
  67. // }
  68. // 需要注意的是,一起删除数组中多个元素的时候,需要从数组的大索引值依次向小索引值删除
  69. for (long i = selectedIndexPaths.count - ; i >= ; i-- ) {
  70. NSIndexPath *indexPath = selectedIndexPaths[i];
  71. [self.dataArrM[indexPath.section] removeObjectAtIndex:indexPath.row];
  72. }
  73. // 在表格中删除单元格
  74. [self.myTable deleteRowsAtIndexPaths:selectedIndexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
  75.  
  76. for (int i = ; i < self.dataArrM.count; i++ ) {
  77. NSMutableArray *arr = self.dataArrM[i];
  78. for (int j = ; j < arr.count ; j++ ) {
  79. NSLog(@"%@", arr[j]);
  80. }
  81. }
  82. }
  83.  
  84. #pragma mark - tableView 的懒加载
  85. // step2 在当前视图中添加tableView
  86. -(UITableView *)myTable{
  87. if ( !_myTable) {
  88. _myTable =[[ UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
  89.  
  90. // _myTable = [[UITableView alloc]initWithFrame:CGRectMake(0, 64, self.view.bounds.size.width, self.view.bounds.size.height - 64 ) style:UITableViewStyleGrouped];
  91. [self.view addSubview:_myTable ];
  92.  
  93. // step3 指定数据源代理, tableview的数据由当前控制器提供
  94. _myTable.dataSource = self; //*********千万别忘记**********
  95. _myTable.delegate = self; //*********千万别忘记**********
  96.  
  97. // 设置表格的footerView
  98. UIView *footerView = [[UIView alloc]initWithFrame:CGRectMake(, , _myTable.frame.size.width, )];
  99. footerView.backgroundColor = [UIColor redColor];
  100. _myTable.tableFooterView = footerView;
  101.  
  102. // 设置表格允许多选
  103. _myTable.allowsMultipleSelection = YES;
  104. _myTable.allowsSelectionDuringEditing = YES;
  105. _myTable.allowsMultipleSelectionDuringEditing = YES;
  106. }
  107. return _myTable;
  108. }
  109.  
  110. #pragma mark - 数组懒加载
  111. -(NSMutableArray *)dataArrM{
  112. if ( !_dataArrM ) {
  113. _dataArrM = [NSMutableArray array];
  114. for (int i = ; i < ; i++ ) {
  115. NSMutableArray *sectionArrM = [NSMutableArray array];
  116. for (int j = ; j < ; j++ ) {
  117. NSString *str = [NSString stringWithFormat:@"第%d组,第%d行", i ,j ];
  118. [sectionArrM addObject:str];
  119. }
  120.  
  121. [_dataArrM addObject:sectionArrM];
  122. }
  123. }
  124. return _dataArrM;
  125. }
  126.  
  127. #pragma mark - 分组是否折叠数据的懒加载
  128. -(NSMutableArray *)sectionShowArrM{
  129. if (!_sectionShowArrM ) {
  130. _sectionShowArrM = [NSMutableArray array];
  131. for (int i = ; i < self.dataArrM.count ; i++ ) {
  132. [_sectionShowArrM addObject:@NO]; // 默认起始状态为收起
  133. }
  134. }
  135. return _sectionShowArrM;
  136. }
  137.  
  138. // step4 实现UITableViewDataSource协议方法
  139. #pragma mark - UITableViewDataSource
  140. // 返回有多少分组
  141. -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
  142. return self.dataArrM.count;
  143. }
  144. // 指定每个分组有多少行,返回0行表示该分组不显示单元格
  145. -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
  146. if ([self.sectionShowArrM[section] boolValue] == YES) {
  147. // 如果sectionShowArrM数组中保存当前分组的状态是YES,为展开状态,返回数组元素的个数
  148. return [self.dataArrM[section] count];
  149. }else{
  150. return ; // 收起状态
  151. }
  152.  
  153. }
  154. // 指定要显示的单元格
  155. -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
  156. // 注册单元格类,并指定重用标识
  157. [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cellID"];
  158. // 从tableView中找一个可重用的单元格,如果没有的话,系统会自动创建一个新的单元格
  159. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellID" forIndexPath:indexPath];
  160. // 指定单元格要显示的内容
  161. cell.textLabel .text = self.dataArrM[indexPath.section][indexPath.row];
  162.  
  163. //返回单元格
  164. return cell;
  165. }
  166. // 每个分组的头标题
  167. - (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
  168.  
  169. return [NSString stringWithFormat:@"第%ld组的头", section];
  170. }
  171. // 每个分组尾部的标题
  172. - (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{
  173. return [NSString stringWithFormat:@"第%ld组的尾部", section];
  174.  
  175. }
  176.  
  177. // 指示是否允许编辑,具体的删除和插入操作由其他协议方法实现
  178. - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
  179. return YES;
  180. }
  181.  
  182. // 指示表格中的行是否可以移动
  183. - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{
  184. return YES;
  185. }
  186.  
  187. // 返回组索引的标题
  188. - (nullable NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView{
  189. NSMutableArray *sectionTitles = [NSMutableArray array];
  190. for (int i = ; i < self.dataArrM.count ; i++ ) {
  191. [sectionTitles addObject: [NSString stringWithFormat:@"%d组", i ]];
  192. }
  193. return sectionTitles;
  194. }
  195.  
  196. //- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index{
  197. // if (index == 2 ) {
  198. // return 0;
  199. // }else {
  200. // return index;
  201. // }
  202. //}
  203.  
  204. // 提交单元格的编辑
  205. - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
  206. if (editingStyle == UITableViewCellEditingStyleDelete) {
  207. // 在数据源数组中删除相应的数据
  208. [self.dataArrM[indexPath.section] removeObjectAtIndex:indexPath.row];
  209. // 刷新表格
  210. [self.myTable deleteRowsAtIndexPaths:@[indexPath ] withRowAnimation:UITableViewRowAnimationAutomatic];
  211. }else if ( editingStyle == UITableViewCellEditingStyleInsert){
  212. // 在数据源数组中插入数据
  213. [self. dataArrM[indexPath.section] insertObject:@"新插入的行" atIndex:indexPath.row ];
  214. // 刷新单元格
  215. [self.myTable insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
  216. }
  217.  
  218. }
  219. // 在该方法中一般实现数据源的交换
  220. - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
  221. // 取出要移动行的内容
  222. NSString *row = self.dataArrM[sourceIndexPath.section][sourceIndexPath.row];
  223. // 在数据源中删除要移动的行
  224. [self.dataArrM[sourceIndexPath.section] removeObjectAtIndex:sourceIndexPath.row];
  225. // 在目的地插入要移动的行数据
  226. [self.dataArrM[destinationIndexPath.section] insertObject:row atIndex:destinationIndexPath.row];
  227. }
  228.  
  229. #pragma mark - UITableViewDelegate
  230. // 将要显示每个分组的footer的时候调用
  231. - (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section{
  232.  
  233. // if (section < self.dataArrM.count - 1 ) {
  234. // return;
  235. // }
  236. //
  237. // //获取更多数据
  238. // NSMutableArray *addRowsArrM = [NSMutableArray array];
  239. // for (int i = 0 ; i < 10 ; i++ ) {
  240. // NSString *addRow = [NSString stringWithFormat:@"新添加的第%d行", i ];
  241. // [addRowsArrM addObject:addRow];
  242. // }
  243. // [self.dataArrM addObject:addRowsArrM];
  244. // //刷新表格
  245. // NSIndexSet *indexSet = [[NSIndexSet alloc]initWithIndex:section];
  246. // [self.myTable reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];
  247. }
  248.  
  249. // 返回第一行的高度
  250. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
  251. return ;
  252. }
  253. // 返回每个分组头部的高度
  254. - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
  255. return ;
  256. }
  257. // 返回每个分组尾部的高度
  258. - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
  259. return ;
  260. }
  261.  
  262. // 返回每个分组头部视图,如果实现了这个协议,tableView:titileForHeaderInSection协议方法不再起作用
  263. - (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
  264. UIButton *headerBtn = [[UIButton alloc]initWithFrame:CGRectMake(, , tableView.frame.size.width, )];
  265. [headerBtn setTitle:[NSString stringWithFormat: @"这是第%ld组的头部", section] forState:UIControlStateNormal] ;
  266. headerBtn.titleLabel.textAlignment = NSTextAlignmentCenter;
  267. headerBtn.backgroundColor = [UIColor orangeColor];
  268.  
  269. // [headerBtn setImage:[UIImage imageNamed:@"icon_back_highlighted"] forState:UIControlStateNormal];
  270. UIImageView *btnImg = [[UIImageView alloc]initWithFrame:CGRectMake(, , , headerBtn.frame.size.height)];
  271. btnImg.contentMode = UIViewContentModeScaleAspectFit;
  272. btnImg.image = [UIImage imageNamed:@"icon_back_highlighted"];
  273. [headerBtn addSubview:btnImg];
  274.  
  275. // 根据当前分组是否折叠来确定图标的旋转
  276. BOOL isShow = [self.sectionShowArrM[section] boolValue];
  277. if (isShow == YES) {
  278. btnImg.transform = CGAffineTransformRotate(btnImg.transform, -M_PI_2);
  279. }else{
  280. btnImg.transform = CGAffineTransformIdentity;
  281. }
  282.  
  283. headerBtn.tag = + section;
  284. // 添加事件
  285. [headerBtn addTarget:self action:@selector(showSection: ) forControlEvents:UIControlEventTouchUpInside];
  286.  
  287. return headerBtn;
  288. }
  289. -(void)showSection:(UIButton *)button{
  290. long sectionIndex = button.tag - ;
  291. // 先获取当前分组的折叠状态
  292. BOOL isShow = [self.sectionShowArrM[sectionIndex] boolValue];
  293. if (isShow == NO ) { // 如果收起状态,点一下后,修改为展开状态
  294. self.sectionShowArrM[sectionIndex] = @YES;
  295. }else { // 展开状态
  296. self.sectionShowArrM[sectionIndex] = @NO;
  297. }
  298. // 刷新当前分组
  299. NSIndexSet *indexSet = [[NSIndexSet alloc] initWithIndex:sectionIndex];
  300. [self.myTable reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];
  301.  
  302. // 让分组头部左侧的图标旋转,这块代码放在这儿不合适,表格刷新后,图标会复位
  303. // 获取当前按钮中的箭头
  304. // UIImageView *btnImg;
  305. // for (UIView *subView in button.subviews) {
  306. // if ([subView isKindOfClass:[UIImageView class]]) {
  307. // btnImg = (UIImageView *)subView;
  308. // break;
  309. // }
  310. // }
  311. //
  312. // btnImg.transform = CGAffineTransformRotate(btnImg.transform , -M_PI_2);
  313. }
  314.  
  315. // 返回每个分组尾部视图
  316. // - (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
  317. //
  318. // }
  319.  
  320. // 返回单元格右侧的辅助按钮的类型
  321. - (UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath {
  322. return UITableViewCellAccessoryDisclosureIndicator;
  323. }
  324. // 当单元格右侧的辅助视图是一个按钮,当点击该按钮时,执行该协议方法
  325. - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{
  326. NSLog(@"detailButton be tapped");
  327. }
  328.  
  329. // 指示是否允许高亮显示选中的行
  330. - (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath{
  331. return YES;
  332. }
  333.  
  334. // 选中某行时执行
  335. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
  336. NSLog(@"selected: %ld, row:%ld", indexPath.section, indexPath.row);
  337. }
  338. // 取消选中时执行,这个方法常在表格允许多选时调用执行
  339. - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{
  340. NSLog(@"Deselected: %ld, row:%ld", indexPath.section, indexPath.row);
  341. }
  342.  
  343. // 返回编辑时,是删除单元格还是插入单元格,要真正的实现删除或者插入操作,必须实现tableView:commitEditingStyle:forRowAtIndexPath:这个协议方法
  344. - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
  345. return UITableViewCellEditingStyleInsert;
  346. }
  347.  
  348. // 单元格的缩进
  349. - (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath{
  350. if(indexPath.row % == ){
  351. return ;
  352. }else{
  353. return ;
  354. }
  355. }
  356.  
  357. @end

UITableView相关知识点

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

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

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

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

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

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

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

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

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

  5. TCP/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_INCREMENT)相关知识点总结

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

随机推荐

  1. 前端构建:Less入了个门

    一.前言   说到前端构建怎能缺少CSS预处理器呢!其实CSS的预处理器有很多啦,比较出名的有Scss.Sass.Stylus和Less.(最近还听说出现了Autoprefixer等CSS后处理器,可 ...

  2. 百度地图API实现地图定位

    1.引用JS: <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0& ...

  3. javascript学习笔记1-document.write

    <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> ...

  4. webstorage[html5的本地数据处理]

    1.webStorage是什么? webStorage是html5中用于本地化存储的一种方式,而在之前呢我们是用cookie的存储方式处理; 2.那它们之间的区别是什么? Ⅰ.cookie存在的问题: ...

  5. archive for required library...

    最近把移动硬盘上的一个Android项目复制到笔记本上面,import后项目文件夹始终有一个红色叹号,console里面提示“archive for required library...”,原来是l ...

  6. JavaScript的DOM操作。Window.document对象

    间隔执行一段代码:window.setlnteval("需要执行的代码",间隔毫秒数) 例 :      window.setlnteval("alert("你 ...

  7. Apache运行python cgi程序

    Apache运行python cgi程序 环境 win10 x64 专业版 Apache2.4 python 2.7 Apache安装和配置 Apache服务器的安装请自行搜索.在Apache2.4中 ...

  8. android自动化之monkeyrunner

    一.使用CMD命令打开模拟器 运行monkeyrunner之前必须先运行相应的模拟器或连上设备,不然monkeyrunner无法连接设备. 1.1  用Elipse打开Android模拟器或在CMD中 ...

  9. Linux下安装DB2_v9.7详细教程

    一:平台 1:HP服务器 cpu:Inter (R) Xeon (R) E5606 2.13G 磁盘:本地磁盘外加存储 2:操作系统 RedHet 5.4 64位 内核:2.6.18-194.1.AX ...

  10. Tab切换类型

    Tab切换类型 点击Tab 滑过Tab 延迟Tab CSS样式 ; ; list-style:none; font-size:12px;} .notice{width:298px; height:98 ...