做爲在開發中最經常使用的一個控件,UITableView也是在整個UIKit中比較複雜的一個,咱們須要記的東西也特別多.另外蘋果官方爲咱們提供了UITableViewController這個類,可是在這裏咱們不使用它.而是在UIViewController上面添加一個UITableView.數組
UITableView繼承於UIScrollView,當須要展現的數據量不少的時候,它是能夠滾動顯示的.bash
表視圖的每一行都是由單元格(UITableViewCell)表示的.當咱們要對數據分組顯示時,蘋果爲咱們提供了兩種基本樣式的顯示,一種是分組樣式,一種則爲簡單樣式.ide
咱們初始化一個UITableView,並指定樣式,而後進行其相關屬性的設置,最後將他添加到控制器上.動畫
// 1.建立tableView(表視圖)並初始化,初始化的時候給一個樣式
UITableView *tableView = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds style:UITableViewStyleGrouped];
// 2.設置屬性
// 設置分割線的顏色
tableView.separatorColor = [UIColor redColor];
// 設置分割線的風格
tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
// 設置行高
tableView.rowHeight = 100;
// 設置tableView的tableHeaderView
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 414, 200)];
headerView.backgroundColor = [UIColor cyanColor];
tableView.tableHeaderView = headerView;
// 設置tableView的tableFooterView(取消下面多餘的線)
UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 20)];
footerView.backgroundColor = [UIColor magentaColor];
tableView.tableFooterView = footerView;
// 設置索引條
tableView.sectionIndexColor = [UIColor blackColor];
// 背景顏色
tableView.sectionIndexBackgroundColor = [UIColor clearColor];
//
tableView.sectionIndexTrackingBackgroundColor = [UIColor lightGrayColor];
// 3.添加到視圖
[self.view addSubview:tableView];
複製代碼
在上面的代碼中,咱們對UITableView的分割線和行高,一塊兒頭尾視圖,索引條這幾個屬性進行了相關設置,對於其餘的屬性,讀者能夠本身根據興趣嘗試設置.ui
在UITableView中用於展現數據的主要就是UITableViewCell.在這裏首相我想先說一下關於UITableViewCell的重用.spa
若是咱們想利用UITableView展現幾條數據的話,咱們能夠依次建立這些數量的行來展現這些數據,可是咱們若是有10000行甚至更多的數據要用來向用戶展現呢?若是反覆建立是十分消耗內存的.代理
這樣咱們就天然的想到,爲何要建立這麼屢次cell呢?咱們爲何不將建立好的cell保存起來,放在一個隊列中重用呢?這就是UITableViewCell的重用機制.當咱們有10000條數據須要展現的時候,咱們使用這個機制建立的行可能僅須要10個,這樣就大大節約了內存.code
咱們能夠從官方的API中看到UITableViewCell的初始化方法.cdn
![UITableViewCell的初始化方法]://upload-images.jianshu.io/upload_images/1230517-db6401da06482690.png)對象
在建立Cell的時候一樣須要指定一個樣式,而且設置一個標識.關於樣式蘋果給定了四個樣式
讀者能夠一一試驗,着這裏就不作詳細的講解.
if (!cell) {
// 若重用池裏面沒有,則去建立identifier標識符的cell
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
}
複製代碼
實際上,上述的建立UITableViewCell的方法是在iOS6以前的老方法.
在iOS6以後咱們只須要註冊在重用池中註冊一下cell的重用標識符.在註冊cell以前咱們必須爲cell設置重用標識符,這個標識符必須惟一.咱們一般聲明爲靜態字符串,咱們不須要管理字符串的內存,也不須要對其進行釋放.
// 聲明重用標識符
static NSString *identifier = @"cellReuse";
複製代碼
// 註冊(iOS6 以後的寫法)
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:identifier];
複製代碼
而後在UITableViewDataSource數據源方法中建立就能夠了
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// 先去重用池裏面取帶有identifier重用標識符的cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
return cell;
}
複製代碼
NSIndexPath表明UITableView的索引.因爲咱們建立的cell是重用的,這樣一來咱們便無法精確的肯定這個行.出於此,系統爲咱們提供了一個標示行的類,就是NSIndexPath
NSIndexPath的經常使用屬性有:
row表示分區中的行的索引,section標示分區的索引.經過這兩個屬性咱們就能夠找到想要的行.
關於UITableViewCell咱們是能夠根據本身的須要自定義的,咱們只須要從新建立一個類繼承自UITableViewCell,在其中設置成須要的樣式.而後在註冊和建立的時候使用自定義的cell就能夠了,在這裏咱們假設咱們建立一個MyTableViewCell,而且設置了重用標識符,那麼註冊和建立的方式以下.
註冊
[self.tableView registerClass:[MyTableViewCell class] forCellReuseIdentifier:identifier];
複製代碼
建立
MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
複製代碼
上面是對UITableView的總體結構介紹,若是咱們要建立表視圖展現數據,咱們必需要爲表視圖設置代理和數據源,也就是UITableViewDelegate和UITableViewDataSource
先看數據源代理,數據源顧名思義,就是爲表視圖提供相關的數據.
咱們看到API中有兩個必需要實現的方法
//分區的個數,也就設置這個表分紅幾組(section)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
//建立或者重用cell的代理方法
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
複製代碼
另外咱們能夠對其每一個分區的行數(row)進行設置,還能夠設置其頭尾(titleForHeaderInSection和titleForFooterInSection).
相對這些我跟想跟你們交流的是一些有趣的方法
使頁面處於可編輯狀態
// 第一步: 使頁面處於可編輯狀態
- (void)edit:(UINavigationController *)sender{
// 設置當前頁面能夠被編輯
// 當點擊編輯的時候,頁面應該處於可編輯狀態,而且按鈕文字變成"完成"
if ([sender.title isEqualToString:@"編輯"]) {
sender.title = @"完成";
[_tableView setEditing:YES animated:YES];
}else{
// 當點擊完成時,應該讓當前頁面處於不可編輯狀態,而且按鈕文字顯示爲"編輯"
sender.title = @"編輯";
[_tableView setEditing:NO animated:YES];
}
}
複製代碼
指定哪些行能夠被編輯
// 指定哪些行能夠被編輯
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.section == 2) {
return NO;
}
return YES;
}
複製代碼
根據路徑指定編輯的樣式
// 根據路徑指定編輯的樣式
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.section == 5) {
return UITableViewCellEditingStyleInsert;
}
return UITableViewCellEditingStyleDelete;
}
複製代碼
根據編輯風格完成編輯(先操做數據,在更新UI)
// 根據編輯風格完成編輯(先操做數據,在更新UI)
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
// 刪除
if (editingStyle == UITableViewCellEditingStyleDelete) {
// 找到對應得分組
NSMutableArray *array = _dataDictionary[_dataArray[indexPath.section]];
// 噹噹前分組只有一我的的時候,刪除元素以後,對應的分組也應該被刪掉
if (array.count == 1) {
// 刪除大字典裏面的該分組
[_dataDictionary removeObjectForKey:_dataArray[indexPath.section]];
// 刪除掉數組裏面對應的key
[_dataArray removeObjectAtIndex:indexPath.section];
// 刪除UI
NSIndexSet *set = [NSIndexSet indexSetWithIndex:indexPath.section];
[tableView deleteSections:set withRowAnimation:UITableViewRowAnimationFade];
}else{
// 刪除數據
[array removeObjectAtIndex:indexPath.row];
// 刪除對應的cell 更新UI
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationMiddle];
}
}else{
// 增長
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:@"悟空",@"name",@"男",@"age",@"八戒",@"hobby",@"18833336666",@"phoneNumber",12,@"age",@"八戒.png",@"picture", nil];
// 找到對應的分組
NSMutableArray *array = _dataDictionary[_dataArray[indexPath.section]];
// 添加元素
[array insertObject:dic atIndex:indexPath.row+1];
// 增長 更新UI
// <1 定義一個新路徑
NSIndexPath *newPath = [NSIndexPath indexPathForRow:indexPath.row+1 inSection:indexPath.section];
[_tableView insertRowsAtIndexPaths:@[newPath] withRowAnimation:UITableViewRowAnimationTop];
}
}
複製代碼
使頁面處於可編輯狀態
// 第一步 使頁面處於可編輯狀態
-(void)setEditing:(BOOL)editing animated:(BOOL)animated{
[super setEditing:editing animated:animated];
[_tableView setEditing:editing animated:animated];
self.navigationItem.rightBarButtonItem.title = editing? @"完成":@"編輯";
}
複製代碼
指定tableView哪些行能夠被移動
// 第二步 指定tableView哪些行能夠被移動
-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{
return YES;
}
複製代碼
移動完成
// 第三步 移動完成
-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
// 獲取移動的數據
NSMutableArray *array = _dataDictionary[_dataArray[sourceIndexPath.section]];
// 獲取移動的對象
NSDictionary *dic = [array objectAtIndex:sourceIndexPath.row];
// 先刪除
[array removeObjectAtIndex:sourceIndexPath.row];
// 再添加
[array insertObject:dic atIndex:destinationIndexPath.row];
}
複製代碼
檢測跨區移動
// 檢測跨區移動
-(NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath{
// 若是就在一個分區,則容許任意移動
if (sourceIndexPath.section == proposedDestinationIndexPath.section) {
return proposedDestinationIndexPath;
}
// 不然原路滾回去
return sourceIndexPath;
}
複製代碼
經常使用的方法還有
// 快速索引
- (nullable NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;
複製代碼
UITableViewDelegate中經常使用方法
// 設置行高
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
複製代碼
// 設置分區的header高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
複製代碼
// 設置分區的footer高度
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
複製代碼
// 設置分區headerView的視圖(設置以後,與titleForHeader方法不共存且設置的高度沒有用,想要肯定,headerView的高度,必須重寫heightForHeaderInSection方法)
- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
複製代碼
// 設置分區footerView的視圖
- (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;
複製代碼
// 點擊觸發事件
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
複製代碼
試想一下,當咱們建立UITableView完成以後,咱們向其中添加或者更改刪除了一條數據,咱們想讓最新的數據呈現出來該怎麼辦呢?很天然的咱們就想到了從新加載一遍,也就是刷新了.
關於刷新數據系統提供給咱們三種方法.
// 刷新整個表格
-(void)reloadData;
複製代碼
// 刷新某些section,animation表示刷新時使用的動畫
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
複製代碼
// 刷新某些row
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
複製代碼
上面說了這麼多,咱們發現建立一個表視圖真的好麻煩,要設置代理和數據源,還有那麼多的方法.那麼有沒有一種更好的方法來替代這些方法呢?答案固然是確定的.爲了提升開發效率,Apple將UITableView和UIViewController結合,產生了UITableViewController.
使用UITableViewController,咱們只須要根據須要使用其方法進行配置就行了.若是搞懂了UITableView,那麼使用UITableViewController就駕輕就熟了,其實這兩個一模一樣,在此就不贅述了.
以上就是UITableView和UITableViewCell的簡單介紹,若是有疑問或者錯誤,歡迎指正交流,我將不勝感激.轉載請保留連接.