目錄主要分爲以下幾個樣式:
常用、會用、瞭解
目錄
- UITableViewDataSource
-
配置TableView
- tableView:cellForRowAtIndexPath:
- tableView:numberOfRowsInSection:
- numberOfSectionsInTableView:
- tableView:titleForHeaderInSection:
- tableView:titleForFooterInSection:
- 插入&&刪除
- tableView:commitEditingStyle:forRowAtIndexPath:
- tableView:canEditRowAtIndexPath:
- 重新排序
- tableView:canMoveRowAtIndexPath:
- tableView:moveRowAtIndexPath:toIndexPath:
- 索引設置
- sectionIndexTitlesForTableView:
- tableView:sectionForSectionIndexTitle:atIndex:
- UITableViewDelegate
-
配置Row
- tableView:heightForRowAtIndexPath:
- tableView:estimatedHeightForRowAtIndexPath:
- tableView:indentationLevelForRowAtIndexPath:
- tableView:willDisplayCell:forRowAtIndexPath:
- tableView:shouldSpringLoadRowAtIndexPath:withContext:
-
擴展按鈕
- tableView:editActionsForRowAtIndexPath:
- tableView:accessoryButtonTappedForRowWithIndexPath:
-
選擇管理
- tableView:willSelectRowAtIndexPath:
- tableView:didSelectRowAtIndexPath:
- tableView:willDeselectRowAtIndexPath:
- tableView:didDeselectRowAtIndexPath:
-
頁眉和頁腳
iOS11需要注意的新特性 -
編輯表單(左滑)
- tableView:willBeginEditingRowAtIndexPath:
- tableView:didEndEditingRowAtIndexPath:
- tableView:editingStyleForRowAtIndexPath:
- tableView:titleForDeleteConfirmationButtonForRowAtIndexPath:
- tableView:shouldIndentWhileEditingRowAtIndexPath:
-
重新排序表單
- tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:
-
移動出可見範圍
- cell/sectionHeaderView/sectionFooterView的消失
- MENU菜單
- 高亮管理
UITableViewDataSource
一個能夠爲UITableView提供展示要素的代理
配置TableView
-
tableView:cellForRowAtIndexPath:
將返回的Cell插入TableView的indexPath位置。(一旦需要展示cell)則必須實現且不能返回nil。
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath;
返回的對象通常是重用的cell。
-
- tableView:numberOfRowsInSection:
返回該節有多少行內容(必須實現)
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section;
-
numberOfSectionsInTableView:
返回一共有多少節內容需要展示
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
默認返回1
-
- tableView:titleForHeaderInSection:
-
- tableView:titleForFooterInSection:
爲系統默認樣式的sectionHeader/sectionFooter設置文字
- (NSString *)tableView:(UITableView *)tableView
titleForHeaderInSection:(NSInteger)section;
除了敲demo通常沒啥用。你應該使用tableView:viewForHeaderInSection:
進行自定義樣式。
插入&&刪除
-
- tableView:commitEditingStyle:forRowAtIndexPath:
編輯完成時調用
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath;
如果點擊其他地方被取消、則不會被調用。
editingStyle
是一個枚舉、有三種可能的值
typedef NS_ENUM(NSInteger, UITableViewCellEditingStyle) {
UITableViewCellEditingStyleNone,//沒有編輯樣式
UITableViewCellEditingStyleDelete,//刪除樣式 (左邊是紅色減號)
UITableViewCellEditingStyleInsert//插入樣式 (左邊是綠色加號)
};
當你進行了對應的操作(點擊了綠色的添加或者紅色的刪除)、代理將會告知你並讓你修改數據源以配合操作。
-
- tableView:canEditRowAtIndexPath:
返回該位置的cell是否可以進入編輯狀態
- (BOOL)tableView:(UITableView *)tableView
canEditRowAtIndexPath:(NSIndexPath *)indexPath;
如果沒有實現此方法、那麼默認所有的cell都可以進入編輯狀態。
這個編輯狀態有兩種意思:
- 通過
[self.tableView setEditing:YES animated:YES];
讓所有cell進入 - 右滑
重新排序
讓tableView支持拖動、需要以下條件
讓tableView進入編輯狀態
也就是設置它的editing爲YES返回編輯模式
也就是實現UITableViewDelegate中的tableview:editingStyleForRowAtIndexPath:方法,在裏面返回UITableViewCellEditingStyleNone模式。如果不實現,默認返回的就是刪除模式
3、實現tableView:moveRowAtIndexPath:toIndexPath
方法
只要實現該方法,就能實現單元格的拖動排序,但只是實現了表面的排序,並沒有修改真實地數據
4、在方法中完成數據模型的更新
-
tableView:canMoveRowAtIndexPath:
是否可以將該cell拖動到指定位
- (BOOL)tableView:(UITableView *)tableView
canMoveRowAtIndexPath:(NSIndexPath *)indexPath;
返回該單元格、是否可以被拖動。默認返回YES。
-
- tableView:moveRowAtIndexPath:toIndexPath:
拖動完成時觸發、讓用戶修改數據源
- (void)tableView:(UITableView *)tableView
moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath
toIndexPath:(NSIndexPath *)destinationIndexPath;
如果不做修改、cell就僅僅是在當前展示上修改了位置。下次被提取或者刷新時會變回原來的順序。
索引設置
-
- sectionIndexTitlesForTableView:
返回索引數組
- (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView;
- tablbView的style必須是
UITableViewStylePlain
- 返回的數組將會懸浮在tableView右側
-
- tableView:sectionForSectionIndexTitle:atIndex:
點擊索引後、將talbeView移動至哪個section處
- (NSInteger)tableView:(UITableView *)tableView
sectionForSectionIndexTitle:(NSString *)title
atIndex:(NSInteger)index;
支持數組越界
UITableViewDelegate
對頁眉頁腳、高度、選擇、刪除等操作進行支持。
配置Row
-
- tableView:heightForRowAtIndexPath:
可以爲指定的行設置高度
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath;
你可以rowHeight
爲所有的cell統一設置高度、相對性能較高。
而一旦實現heightForRowAtIndexPath
方法、你就必須爲每一個indexPath設置高度。
返回UITableViewAutomaticDimension
則由系統自適應計算。
-
- tableView:estimatedHeightForRowAtIndexPath:
返回指定位置的預估行高
- (CGFloat)tableView:(UITableView *)tableView
estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath;
- 如果沒有預估、可以返回
UITableViewAutomaticDimension
。 - 使用此功能可以將某些計算、從加載時移動到滾動時進行。以提高性能。
-
- tableView:indentationLevelForRowAtIndexPath:
返回縮進級別
- (NSInteger)tableView:(UITableView *)tableView
indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath;
並不知道有什麼地方必須這樣用
-
- tableView:willDisplayCell:forRowAtIndexPath:
某個indexPath的cell將要被繪製(展示)
- (void)tableView:(UITableView *)tableView
willDisplayCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath;
由於cellForRow
實際上會預創建一些cell、所以cell內部的賦值可以放在這裏、以提升一些性能。
但是最顯著的用途還是對剛展示出來的cell做一些動畫吧。比如從右側一個一個滑入之類。
-
- tableView:shouldSpringLoadRowAtIndexPath:withContext:
cell是否支持iOS11 新特性 Drag and Drop (默認YES)
- (BOOL)tableView:(UITableView *)tableView
shouldSpringLoadRowAtIndexPath:(NSIndexPath *)indexPath
withContext:(id<UISpringLoadedInteractionContext>)context;
擴展按鈕
-
- tableView:editActionsForRowAtIndexPath:
自定義左滑事件
- (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView
editActionsForRowAtIndexPath:(NSIndexPath *)indexPath;
返回一個由UITableViewRowAction
組成的數組。
他們會響應用對應的點擊交互。
如果你不實現這個代理、右滑時將會展示默認按鈕。
-
- tableView:accessoryButtonTappedForRowWithIndexPath:
當cell的擴展視圖被點擊時調用
- (void)tableView:(UITableView *)tableView
accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath;
這裏的擴展視圖指的是cell.accessoryType
的視圖。如下圖所示:
選擇管理
cell被點擊時引起的一系列方法調用
需要注意的是即使cell.selectionStyle = UITableViewCellSelectionStyleNone;
使得cell跟隨點擊而改變背景色、以下方法也會被調用。
-
- tableView:willSelectRowAtIndexPath:
將要被選定時觸發
- (NSIndexPath *)tableView:(UITableView *)tableView
willSelectRowAtIndexPath:(NSIndexPath *)indexPath;
允許你通過返回一個新的NSIndexPath
、來修改將要被選擇的cell。
編輯狀態下不會觸發此方法
-
- tableView:didSelectRowAtIndexPath:
cell被選定時觸發
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
編輯狀態下不會觸發此方法
-
- tableView:willDeselectRowAtIndexPath:
選中狀態被取消時觸發
- (NSIndexPath *)tableView:(UITableView *)tableView
willDeselectRowAtIndexPath:(NSIndexPath *)indexPath;
如果你返回nil、將不會被取消。允許從定向
-
- tableView:didDeselectRowAtIndexPath:
cell選中被取消時觸發
- (void)tableView:(UITableView *)tableView
didDeselectRowAtIndexPath:(NSIndexPath *)indexPath;
頁眉和頁腳
//返回頁眉和頁腳
- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
- (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;
//返回頁眉和頁腳的高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
//頁眉和頁腳將要展示
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
//預估頁眉和頁腳高度
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section NS_AVAILABLE_IOS(7_0);
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section NS_AVAILABLE_IOS(7_0);
以上的方法通過方法名基本都能理解其用處。
這裏需要注意
iOS11之後、系統爲我們設置了預估行高。如果只實現了header
高度爲0.1f
、而沒有返回具體的view會引起留白的bug。《詳見》
編輯表單
要讓表單支持左滑
你必須實現commitEditingStyle
方法、以告訴tableView左滑操作是由價值的
-
- tableView:willBeginEditingRowAtIndexPath:
表單即將進入編輯模式(左滑)
- (void)tableView:(UITableView *)tableView
willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath;
-
-tableView:didEndEditingRowAtIndexPath:
已經離開編輯模式
- (void)tableView:(UITableView *)tableView
didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath;
編輯接觸(並不限於取消)觸發、並不會記錄你執行了哪種操作。
所以、你應該在tableView:commitEditingStyle:forRowAtIndexPath:
而不是這裏實現相關編輯操作。
-
- tableView:editingStyleForRowAtIndexPath:
決定左滑返回哪種附加視圖
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView
editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;
默認返回UITableViewCellEditingStyleDelete
typedef NS_ENUM(NSInteger, UITableViewCellEditingStyle) {
UITableViewCellEditingStyleNone,//沒有編輯樣式
UITableViewCellEditingStyleDelete,//刪除樣式 (左邊是紅色減號)
UITableViewCellEditingStyleInsert//插入樣式 (左邊是綠色加號)
};
-
- tableView:titleForDeleteConfirmationButtonForRowAtIndexPath:
更改
UITableViewCellEditingStyleDelete
下的文字
- (NSString *)tableView:(UITableView *)tableView
titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath;
對setEditing
以及左滑時同樣有效。
-
- tableView:shouldIndentWhileEditingRowAtIndexPath:
進入編輯模式時、cell背景是否縮進
- (BOOL)tableView:(UITableView *)tableView
shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath;
通知委託在編輯模式下是否需要對錶視圖指定行進行縮進,NO爲關閉縮進,這個方法可以用來去掉move時row前面的空白。
重新排序表單
-
tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:
在移動cell的時候會多次調用
- (NSIndexPath *)tableView:(UITableView *)tableView
targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath;
cell的初始位置以及目標。允許對目標位置重定向。
移動中的留白動畫、以及結果都會受此影響。
移動出可見範圍
cell/sectionHeaderView/sectionFooterView的消失
//cell已經移動出可見範圍
- (void)tableView:(UITableView *)tableView
didEndDisplayingCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath;
//sectionHeaderView已經移動出可見範圍
- (void)tableView:(UITableView *)tableView
didEndDisplayingHeaderView:(UIView *)view
forSection:(NSInteger)section;
//sectionFooterView已經移動出可見範圍
- (void)tableView:(UITableView *)tableView
didEndDisplayingFooterView:(UIView *)view
forSection:(NSInteger)section;
MENU菜單
如果想讓cell支持menu菜單的呼出、必須將以下三個方法全部實現
-
- tableView:shouldShowMenuForRowAtIndexPath:
長按後是否顯示編輯菜單
- (BOOL)tableView:(UITableView *)tableView
shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath;
-
- tableView:canPerformAction:forRowAtIndexPath:withSender:
返回該cell支持那種action
- (BOOL)tableView:(UITableView *)tableView
canPerformAction:(SEL)action
forRowAtIndexPath:(NSIndexPath *)indexPath
withSender:(id)sender;
這個規則你可以參考iOS文檔補完計劃--UIResponder中關於canPerformAction:withSender:
方法的解釋。
-
- tableView:performAction:forRowAtIndexPath:withSender:
讓代理者對menu操作進行響應
- (void)tableView:(UITableView *)tableView
performAction:(SEL)action
forRowAtIndexPath:(NSIndexPath *)indexPath
withSender:(id)sender;
高亮管理
高亮權限、高亮、取消高領
//點擊時是否高亮。默認YES
- (BOOL)tableView:(UITableView *)tableView
shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath;
//已經高亮
- (void)tableView:(UITableView *)tableView
didHighlightRowAtIndexPath:(NSIndexPath *)indexPath;
//不再高亮
- (void)tableView:(UITableView *)tableView
didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath;
最後
本文主要是自己的學習與總結。如果文內存在紕漏、萬望留言斧正。如果願意補充以及不吝賜教小弟會更加感激。
參考資料
官方文檔-UITableView
iOS UITableView 的 Plain和Grouped樣式的區別
iOS_UITableView 編輯(cell的插入, 刪除, 移動)
ios tableView那些事 (五) 給tableview設置縮進級別
關於UITableView委託方法的功能(by atany)