UITableView全面解析

1.概念

它是基于UIScrollView的列表互動類。使用UITableView可以在屏幕上顯示單元格的列表,每個單元格中還可以包含多項信息,在使用表格視圖時,我們還可以將這些單元格劃分為多個分區(qū)(section),以便將信息分為若干組,總而言之就是表格視圖非常有用。使用它比較簡單,通常4個步驟:創(chuàng)建UITableView的對象、綁定數(shù)據(jù)源和委托、獲得數(shù)據(jù)模型、編寫回調方法。當然,還可以通過繼承或直接使用UITableViewController的方式來顯示表格視圖,但是我個人比較推薦的方式是根據(jù)需要直接創(chuàng)建UITableView的對象,通過委托及數(shù)據(jù)源對UITableView對象進行定制,再將定制好的UITableViewCell作為表格視圖的單元格置于表格視圖中。UITableView的設計嚴格遵循了MVC模式,通過數(shù)據(jù)源提供的模型來生成與表格內容有關的信息,數(shù)據(jù)源委托相當于控制器,當用戶想要選擇或編輯表格內容時,應用程序通過委托來響應這些變化,操作成功后還能夠刷新數(shù)據(jù)模型以反映用戶所做的修改。

2.結構

tableView層次結構

contentView下默認有3個子視圖

2個是UILabel(textLabel、detailTextLabel)

1個UIImageView(imageView)

UITableViewCellStyle屬性:

用于決定使用contentView的哪些子視圖,以及這些子視圖在contentView中的位置

3.cell簡單認識

1.cell的結構

2.cell重用原理

1.當滾動列表時,部分UITableViewCell會移出窗口,UITableView會將窗口外的UITableViewCell放入一個對象池中,等待重用。2.當UITableView要求dataSource返回UITableViewCell時,dataSource會先查看這個對象池,如果池中有未使用的UITableViewCell,dataSource會用新的數(shù)據(jù)配置這個UITableViewCell,然后返回給UITableView,重新顯示到窗口中,從而避免創(chuàng)建新對象

3.不同類型的Cell重用

解決方案:指定不同類型對應的重用標識來區(qū)分

1.UITableViewCell有個NSString*reuseIdentifier屬性,可以在初始化UITableViewCell的時候傳入一個特定的字符串標識來設置reuseIdentifier(一般用UITableViewCell的類名)。2.當UITableView要求dataSource返回UITableViewCell時,先通過一個字符串標識到對象池中查找對應類型的UITableViewCell對象,如果有,就重用,如果沒有,就傳入這個字符串標識來初始化一個UITableViewCell對象

4.注冊cell

1.用類名注冊[self.tableView registerClass:[TagCellclass]forCellReuseIdentifier:@"tgID"];2.通過xib / storyboard畫的,注冊 如下兩張圖:

屏幕快照 2016-08-26 下午4.57.46.png

后面復用

屏幕快照 2016-08-26 下午4.58.17.png

5.iOS8 , 自動計算Cell高度

// 告訴tableView的真實高度是自動計算的,根據(jù)你的約束來計算self.tableView.rowHeight =UITableViewAutomaticDimension;// 告訴tableView所有cell的估計行高self.tableView.estimatedRowHeight =44// 返回估算告訴,作用:在tablView顯示時候,先根據(jù)估算高度得到整個tablView高,而不必知道每個cell的高度,從而達到高度方法的懶加載調用

4. 常用屬性

// 1.UITableView的兩種樣式UITableViewStylePlain/UITableViewStyleGrouped// 2.設置背景顏色self.tableView.backgroundColor = [UIColorpurpleColor];// 3.設置索引條內部文字顏色self.tableView.sectionIndexColor = [UIColorcolorWithRed:1green:1blue:1alpha:1];// 4.設置索引條背景顏色self.tableView.sectionIndexBackgroundColor = [UIColorcolorWithRed:0green:0blue:0alpha:1];//5. 修改tableView的行高self.tableView.rowHeight =100;// 6.組頭組尾的高self.tableView.sectionHeaderHeight =55;self.tableView.sectionFooterHeight =22;// 7.設置整個tablView的頭部/尾部視圖self.tableView.tableHeaderView = [[UISwitchalloc] init];self.tableView.tableFooterView = [UIButtonbuttonWithType:UIButtonTypeInfoDark];// 8.設置我們分割線顏色(clearColor相當于取消系統(tǒng)分割線)self.tableView.separatorColor = [UIColorclearColor];// 9.設置分割線樣式(此為不要分割線None)self.tableView.separatorStyle =UITableViewCellSeparatorStyleNone;// 10.cell不讓選中[cell setSelectionStyle:UITableViewCellSelectionStyleNone]; 或者:cell.selectionStyle =UITableViewCellSelectionStyleNone;

5.常用方法

#pragma mark - 數(shù)據(jù)源方法// 返回行數(shù)- (NSInteger)tableView:(nonnullUITableView*)tableView numberOfRowsInSection:(NSInteger)section{}// 設置cell- (UITableViewCell*)tableView:(nonnullUITableView*)tableView cellForRowAtIndexPath:(nonnullNSIndexPath*)indexPath{}#pragma mark - 代理方法// 設置行高- (CGFloat)tableView:(nonnullUITableView*)tableView heightForRowAtIndexPath:(nonnullNSIndexPath*)indexPath{return100;}// 添加每組的組頭- (UIView*)tableView:(nonnullUITableView*)tableView viewForHeaderInSection:(NSInteger)section{ }// 返回每組的組尾- (UIView*)tableView:(nonnullUITableView*)tableView viewForFooterInSection:(NSInteger)section{ }// 選中某行cell時會調用- (void)tableView:(nonnullUITableView*)tableView didSelectRowAtIndexPath:(nonnullNSIndexPath*)indexPath{NSLog(@"選中didSelectRowAtIndexPath row = %ld", indexPath.row);}// 取消選中某行cell會調用 (當我選中第0行的時候,如果現(xiàn)在要改為選中第1行 - 》會先取消選中第0行,然后調用選中第1行的操作)- (void)tableView:(nonnullUITableView*)tableView didDeselectRowAtIndexPath:(nonnullNSIndexPath*)indexPath{NSLog(@"取消選中 didDeselectRowAtIndexPath row = %ld ", indexPath.row);}// 設置UITableView的索引條,返回數(shù)組字符串集- (nullableNSArray *)sectionIndexTitlesForTableView:(UITableView*)tableView;

6.創(chuàng)建UITableView大致過程總結

1.表格的樣式:iPhone上的表格分為普通樣式和分組樣式。在默認情況下,普通樣式的背景是白色,上面會有透明的單元格。如果希望改變表格樣式,需要在初始化時進行指定,一旦初始化完畢是不能夠更改表格樣式的。

2.設置數(shù)據(jù)源:設置UITableView的dataSource屬性,該屬性對應的指針指向的對象必須遵循UITableViewDataSource協(xié)議,并實現(xiàn)協(xié)議中的相關方法。通過該數(shù)據(jù)源除了獲得單元格的數(shù)據(jù)之外,還可以指定表格中的分區(qū)數(shù),每個分區(qū)的單元格數(shù)量,分區(qū)的頭尾的標題,分區(qū)的索引等內容。

3.指定單元格:可以通過NSIndexPath變量來確定一個單元格,NSIndexPath結構體有兩個成員,一個是section,一個是row,分別表示單元格所在的分區(qū)和分區(qū)中的第幾行。

4.注冊單元格:創(chuàng)建表格視圖時,應該及早注冊表格中使用的單元格,注冊之后應該盡可能復用注冊好的單元格而不是重復創(chuàng)建新的單元格,這種復用對節(jié)省內存是極好的。在注冊的時候可以使用一個字符串作為標識符,稍后可以通過這個標識符獲得可復用單元格。

5.設置委托:可以通過UITableView對象的delegate屬性來對用戶操作做出響應,可以響應表格滾動,用戶編輯或者選中某行等事件。該屬性代表的指針會指向一個遵循UITableViewDelegate協(xié)議的對象,由該對象負責實現(xiàn)事件發(fā)生時的回調方法。

7.常用功能講解

7.1代碼自定義不等高cell

1.新建一個繼承自UITableViewCell的類2.重寫initWithStyle:reuseIdentifier:方法? ? 1).添加所有需要顯示的子控件(不需要設置子控件的數(shù)據(jù)和fram,子? ? ? ? ? 控件要添加到contentView中)? ? 2).進行子控件一次性的屬性設置(有些屬性只需要設置一次, 比如字體\固定的圖片)3.提供2個模型? ? 1).數(shù)據(jù)模型: 存放文字數(shù)據(jù)\圖片數(shù)據(jù)? ? 2).frame模型: 存放數(shù)據(jù)模型\所有子控件的frame\cell的高度4.cell擁有一個frame模型(不要直接擁有數(shù)據(jù)模型)5.重寫frame模型屬性的setter方法: 在這個方法中設置子控件的顯示數(shù)據(jù)和frame6.frame模型數(shù)據(jù)的初始化已經(jīng)采取懶加載的方式(每一個cell對應的frame模型數(shù)據(jù)只加載一次)

7.2全局刷新、局部刷新

1).全局刷新

[self.tableView reloadData];

2).局部刷新

(1)局部section刷新

NSIndexSet* nd=[[NSIndexSetalloc]initWithIndex:1];//刷新第二個section[tableView reloadSections:nd withRowAnimation:UITableViewRowAnimationAutomatic];另外寫法:[tableView reloadSections:[NSIndexSetindexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationAutomatic];

(2)局部cell刷新

reloadRowsAtIndexPaths

例如:

NSIndexPath*te=[NSIndexPathindexPathForRow:2inSection:0];//刷新第一個section的第二行[tableView reloadRowsAtIndexPaths:[NSArrayarrayWithObjects:te,nil] withRowAnimation:UITableViewRowAnimationMiddle];另外寫法:[tableView reloadRowsAtIndexPaths:@[[NSIndexPathindexPathForRow:2inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];

修改Cell的模型數(shù)據(jù)可以使用reloadRowsAtIndexPaths...進行局部刷新

該方法使用的前提是模型數(shù)據(jù)的個數(shù)不變,因為修改并未修改模型數(shù)據(jù)的個數(shù),所以可以使用該方法進行局部刷新

[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationBottom];

刪除局部刷新,刪除調用deleteRowsAtIndexPaths...方法

注意:這里注意,和添加操作一樣我們不能使用UITableView提供的reloadRowsAtIndexPaths...方法 -> 使用的前提是模型數(shù)據(jù)數(shù)量不變

[self.tableView deleteRowsAtIndexPaths:@[[NSIndexPathindexPathForRow:0inSection:0]] withRowAnimation:UITableViewRowAnimationMiddle];

7.3tableView的編輯

UITableView有一個名為editing的屬性,如果將其設置為YES,UITableView就會進入編輯模式。UITableView在編輯模式下,用戶可以管理UITableView中的表格行,例如添加、刪除和移動等操作,但是編輯模式?jīng)]有修改行的功能。

切換編輯模式:setEditing:animated:

增加行:insertRowsAtIndexPaths:withRowAnimation:

刪除行:deleteRowsAtIndexPaths:withRowAnimation:

移動行:moveRowAtIndexPath:toIndexPath:

開始/結束更新:beginUpdates/endUpdates

刷新表格數(shù)據(jù):reloadData

刷新指定位置數(shù)據(jù):reloadRowsAtIndexPaths:withRowAnimation:

刷新指定區(qū)段數(shù)據(jù):reloadSections:withRowAnimation:

左滑功能

1、 讓UITableView進入編輯狀態(tài),會出現(xiàn)左滑效果

// self.tableView.editing = YES;// self.tableView.editing = !self.tableView.editing; [self.tableView setEditing:!self.tableView.editing animated:YES];

2、 代理方法處理左滑效果時編輯事件處理

// 只要實現(xiàn)了這個方法,左滑出現(xiàn)刪除按鈕的功能就有了點擊了左滑出現(xiàn)的“刪除”按鈕就會調用typedefNS_ENUM(NSInteger,UITableViewCellEditingStyle) {UITableViewCellEditingStyleNone,UITableViewCellEditingStyleDelete,UITableViewCellEditingStyleInsert}; - (void)tableView:(UITableView*)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath*)indexPath

3、返回左滑右邊執(zhí)行刪除操作按鈕文字

- (NSString*)tableView:(nonnullUITableView*)tableViewtitleForDeleteConfirmationButtonForRowAtIndexPath:(nonnullNSIndexPath*)indexPath;

4.設置左滑顯示對應按鈕及其處理事件

- (nullableNSArray *)tableView:(UITableView*)tableView editActionsForRowAtIndexPath:(NSIndexPath*)indexPathNS_AVAILABLE_IOS(8_0);

項目中的左滑刪除功能代碼(掃碼上車):

selectPassengerList:這個是可變數(shù)組,裝cell的數(shù)據(jù)

屏幕快照 2017-05-15 下午4.09.09.png

屏幕快照 2017-05-15 下午4.04.58.png

補充1:左滑顯示多個按鈕(自定義)

例子:左滑顯示編輯和刪除按鈕

屏幕快照 2017-10-16 下午4.26.43.png

屏幕快照 2017-10-16 下午4.28.24.png

屏幕快照 2017-10-16 下午4.29.42.png

補充2:實現(xiàn)左滑調接口刪除

刪除部分代碼

刪除成功的回調

其他例子圖片:

屏幕快照 2018-11-07 下午5.05.32.png

https://zhidao.baidu.com/question/754485262492780924.html

7.4tableView的內容能穿透導航欄與TabBar,而且內容都不被它們擋住

7.4如何實現(xiàn)水平滾動的UITableView

8.普通型表格視圖~~~代碼

屏幕快照 2016-08-05 上午11.17.01.png

屏幕快照 2016-08-05 上午11.17.34.png

#pragma mark UITableViewDelegate相關回調方法// 選中單元格的回調方法- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath {}

運行結果如下圖:

屏幕快照 2016-08-05 上午11.19.17.png

9.分組類表格視圖~~~代碼

可以將表格的內容分為若干個分區(qū),事實上保存表格數(shù)據(jù)模型的數(shù)組中的元素也是數(shù)組,那么每個數(shù)組就是一個分區(qū),數(shù)組中的元素對應著分區(qū)中的行??梢詾榉謪^(qū)建立索引以方便的切換到分區(qū),也可以對分區(qū)的頭尾進行定制,這些也是通過表格視圖的數(shù)據(jù)源和委托來實現(xiàn)的。下面的例子演示了如何創(chuàng)建有若干個分區(qū)的表格視圖。

1).普通的分組類型代碼如下

屏幕快照 2016-08-07 上午1.18.32.png

屏幕快照 2016-08-07 上午1.18.49.png

屏幕快照 2016-08-07 上午1.19.03.png

屏幕快照 2016-08-07 上午1.19.36.png

屏幕快照 2016-08-07 上午1.21.15.png

2).自己稍微定制一下(頭部用按鈕,可以展開)

// //獲得分組標題名稱的回調方法//- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {//? ? static NSArray *titles = nil;//? ? if (!titles) {//? ? ? ? titles = @[@"A組", @"B組", @"C組", @"D組"];//? ? }//? ? return titles[section];//}將這段代碼換成"按鈕"的- (UIView*)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section {staticNSArray*titles =nil;if(!titles) {? ? ? ? titles = @[@"A組",@"B組",@"C組",@"D組"];? ? }UIButton*headerButton = [UIButtonbuttonWithType:UIButtonTypeCustom];? ? headerButton.frame =CGRectMake(0,0, WIDTH,30);? ? [headerButton setTitle:titles[section] forState:UIControlStateNormal];? ? headerButton.titleLabel.font = [UIFontsystemFontOfSize:22];? ? [headerButton setTitleColor:[UIColoryellowColor] forState:UIControlStateNormal];? ? [headerButton setBackgroundColor:[UIColorblueColor]];? ? headerButton.tag = section +200;? ? [headerButton addTarget:selfaction:@selector(headerButtonClicked:) forControlEvents:UIControlEventTouchUpInside];returnheaderButton;}- (void)headerButtonClicked:(UIButton*) sender {? ? folded[sender.tag -200] = !folded[sender.tag -200];// 刷新表格[myTableView reloadData];}備注:索引的方法//獲得索引的回調方法- (NSArray*)sectionIndexTitlesForTableView:(UITableView*)tableView {return@[@"金",@"木",@"水",@"火",@"土"];}

創(chuàng)建表格時指定樣式為分組的結果

屏幕快照 2016-08-07 上午1.27.15.png

指定樣式為普通時的結果

屏幕快照 2016-08-07 上午1.28.32.png

10.表格視圖的編輯操作

工具類

.h+ (UIColor*) randomLightColor;.m+ (UIColor*) randomLightColor {CGFloatred = (arc4random() %128+128) /255.0;CGFloatgreen = (arc4random() %128+128) /255.0;CGFloatblue = (arc4random() %128+128) /255.0;return[UIColorcolorWithRed:red green:green blue:blue alpha:1];}

模型

屏幕快照 2016-08-29 上午11.21.04.png

屏幕快照 2016-08-29 上午11.21.41.png

屏幕快照 2016-08-29 上午11.21.54.png

屏幕快照 2016-08-29 上午11.22.12.png

(這個的.m為空)

控制器

屏幕快照 2016-08-27 下午5.07.28.png

屏幕快照 2016-08-27 下午5.08.00.png

屏幕快照 2016-08-27 下午5.08.25.png

屏幕快照 2016-08-27 下午5.08.43.png

屏幕快照 2016-08-27 下午5.09.09.png

屏幕快照 2016-08-27 下午5.09.23.png

屏幕快照 2016-08-27 下午5.09.42.png

屏幕快照 2016-08-27 下午5.10.18.png

效果

屏幕快照 2016-08-27 下午5.06.12.png

屏幕快照 2016-08-27 下午5.06.40.png

11.如何在一個視圖控制器里添加多個UITableview?

效果圖:

1388997-400a1c03a88645d6-1.png

代碼如下:

#import"ViewController.h"#import"MyTableViewCell.h"@interfaceViewController(){NSMutableArray*dataArray1;NSMutableArray*dataArray2;UITableView*mytableViewLeft;UITableView*mytableViewRight;}@end@implementationViewController- (void)viewDidLoad {? ? [superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.mytableViewLeft = [[UITableViewalloc] initWithFrame:CGRectMake(0,10,330,350) style:UITableViewStylePlain];? ? [self.view addSubview:mytableViewLeft];? ? mytableViewLeft.delegate =self;? ? mytableViewLeft.dataSource =self;// 定制單元格[mytableViewLeft registerNib:[UINibnibWithNibName:@"MyTableViewCell"bundle:[NSBundlemainBundle]] forCellReuseIdentifier:@"CELL"];? ? mytableViewRight = [[UITableViewalloc] initWithFrame:CGRectMake(333,10,330,350) style:UITableViewStylePlain];? ? [self.view addSubview:mytableViewRight];? ? mytableViewRight.delegate =self;? ? mytableViewRight.dataSource =self;? ? [selfloadData];}- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section{if(tableView == mytableViewLeft) {returndataArray1.count;? ? }else{returndataArray2.count;? ? }}- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath{if(tableView == mytableViewLeft) {return80;? ? }else{return40;? ? }}- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath{if(tableView == mytableViewLeft) {? ? ? ? MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CELL"forIndexPath:indexPath];? ? ? ? cell.titleLabel.text = dataArray1[indexPath.row];returncell;? ? }else{UITableViewCell*cell = [tableView dequeueReusableCellWithIdentifier:@"cell2"];if(!cell) {? ? ? ? ? ? cell = [[UITableViewCellalloc] initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:@"cell2"];? ? ? ? }? ? ? ? cell.textLabel.text = dataArray2[indexPath.row];returncell;? ? }}// 獲取數(shù)據(jù)- (void) loadData{if(!dataArray1) {? ? ? ? dataArray1 = [NSMutableArrayarray];? ? }for(inti=0; i<10; i++) {NSString*str = [NSStringstringWithFormat:@"左 %d",i];? ? ? ? [dataArray1 addObject:str];? ? }if(!dataArray2) {? ? ? ? dataArray2 = [NSMutableArrayarray];? ? }for(inti=0; i<15; i++) {NSString*str = [NSStringstringWithFormat:@"右 %d",i];? ? ? ? [dataArray2 addObject:str];? ? }}- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath{if(tableView == mytableViewLeft) {NSLog(@"%@",[NSStringstringWithFormat:@"左邊 第 %ld 行",indexPath.row +1]);? ? }else{NSLog(@"%@",[NSStringstringWithFormat:@"右邊 第 %ld 行",indexPath.row +1]);? ? }}@end

12.去掉tableview頂端粘滯效果

- (void)scrollViewDidScroll:(UIScrollView*)scrollView {CGFloatsectionHeaderHeight =30;if(scrollView.contentOffset.y <= sectionHeaderHeight && scrollView.contentOffset.y >=0) {? ? ? ? ? ? ? ? scrollView.contentInset =UIEdgeInsetsMake(-scrollView.contentOffset.y,0,0,0);? ? }elseif(scrollView.contentOffset.y >= sectionHeaderHeight) {? ? ? ? ? ? ? ? scrollView.contentInset =UIEdgeInsetsMake(-sectionHeaderHeight,0,0,0);? ? }}

補充相關內容

表格視圖實現(xiàn)單選與復選:

http://m.blog.csdn.net/article/details?id=51375476

作者:_啊祥同學

鏈接:http://www.lxweimin.com/p/e43228201a8b

來源:簡書

簡書著作權歸作者所有,任何形式的轉載都請聯(lián)系作者獲得授權并注明出處。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容