轉(zhuǎn)載:UITableView 編輯模式詳解
作者:秋刀生魚片
UITableView
的相關(guān)編輯操作非常全,今天我們來做一個總結(jié)蕾殴。跟編輯相關(guān)的屬性和接口有如下笑撞,我們一個一個分析,我們先認(rèn)真閱讀一下相關(guān)頭文件钓觉,我根據(jù)意思大概翻譯了一下注釋茴肥。
1、屬性方法
@property (nonatomic, getter=isEditing) BOOL editing;
// 默認(rèn)狀態(tài)是非編輯狀態(tài)荡灾,如果不調(diào)用下面接口直接設(shè)置瓤狐,是沒有動畫的
- (void)setEditing:(BOOL)editing animated:(BOOL)animated;
2、DataSource
// 當(dāng)增減按鈕按下時批幌,用來處理數(shù)據(jù)和UI的回調(diào)础锐。
// 8.0版本后加入的UITableViewRowAction不在這個回調(diào)的控制范圍內(nèi),UITableViewRowAction有單獨的回調(diào)Block荧缘。
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
// 這個回調(diào)實現(xiàn)了以后皆警,就會出現(xiàn)更換位置的按鈕,回調(diào)本身用來處理更換位置后的數(shù)據(jù)交換截粗。
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;
// 這個回調(diào)決定了在當(dāng)前indexPath的Cell是否可以編輯信姓。
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;
// 這個回調(diào)決定了在當(dāng)前indexPath的Cell是否可以移動。
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;
3绸罗、Delegate
// 這個回調(diào)很關(guān)鍵意推,返回Cell的編輯樣式。
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;
// 刪除按鈕的文字
- (nullable NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED;
// 8.0后側(cè)滑菜單的新接口从诲,支持多個側(cè)滑按鈕左痢。
- (nullable NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(8_0) __TVOS_PROHIBITED;
// 這個接口決定編輯狀態(tài)下的Cell是否需要縮進(jìn)。
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath;
// 這是兩個狀態(tài)回調(diào)
- (void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath __TVOS_PROHIBITED;
- (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath __TVOS_PROHIBITED;
4、編輯狀態(tài)
UITableView
通過editing屬性控制編輯狀態(tài)俊性,調(diào)用- (void)setEditing:(BOOL)editing animated:(BOOL)animated
接口略步,可以決定是否使用原生的變換動畫。
當(dāng)調(diào)用這個接口定页,并將editing設(shè)為YES
是趟薄,UITableView
將開始詢問代理(Delegate)需要編輯哪些Cell,用什么樣的方式編輯典徊。
首先調(diào)用回調(diào)方法- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;
杭煎,這里需要返回YES
;
然后依次為各個Cell調(diào)用- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;
方法獲取編輯樣式卒落。
typedef NS_ENUM(NSInteger, UITableViewCellEditingStyle) {
UITableViewCellEditingStyleNone,
UITableViewCellEditingStyleDelete,
UITableViewCellEditingStyleInsert
};
編輯樣式枚舉有三種羡铲,位運算組合則由不同的用途。
UITableViewCellEditingStyleNone 沒有編輯樣式
UITableViewCellEditingStyleDelete 刪除樣式 (左邊是紅色減號)
UITableViewCellEditingStyleInsert 插入樣式 (左邊是綠色加號)
UITableViewCellEditingStyleDelete|UITableViewCellEditingStyleInsert 多選模式儡毕,左邊是藍(lán)色對號
特別注意也切,右邊的移動并不是這里控制的,需要實現(xiàn)下面這個回調(diào)才會出現(xiàn)腰湾。
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;
另外對于新手來說雷恃,要明白這里的回調(diào)都沒有對UI和數(shù)據(jù)進(jìn)行操作,開發(fā)者需要在回調(diào)中费坊,完成相應(yīng)的操作倒槐。比如刪除或者添加一條數(shù)據(jù),應(yīng)在
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
上面這個回調(diào)中附井,根據(jù)editingStyle進(jìn)行判斷讨越,處理對應(yīng)的UI和數(shù)據(jù)。
5羡忘、8.0版本后的多選側(cè)滑菜單
8.0版本后谎痢,短信等原生應(yīng)用都有了側(cè)滑多按鈕選擇,原來是蘋果的前端團(tuán)隊為TableView加入相關(guān)接口卷雕,這里給個例子
- (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
return @[
[UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:NSLocalizedString(@"編輯", nil) handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
}],
[UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:NSLocalizedString(@"刪除", nil) handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
}]
];
}
6节猿、數(shù)據(jù)與UI更新
數(shù)據(jù)更新沒什么好說的,直接操作數(shù)據(jù)容器就好漫雕,無論是數(shù)組滨嘱、字典還是CoreData數(shù)據(jù)。UI更新則需要使用TableView的方法浸间,如果需求reloadData無法滿足太雨,則必須使用下面的方法
- (void)beginUpdates; // allow multiple insert/delete of rows and sections to be animated simultaneously. Nestable
- (void)endUpdates; // only call insert/delete/reload calls or change the editing state inside an update block. otherwise things like row count, etc. may be invalid.
- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation NS_AVAILABLE_IOS(3_0);
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection NS_AVAILABLE_IOS(5_0);
- (void)insertRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
- (void)deleteRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
- (void)reloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation NS_AVAILABLE_IOS(3_0);
- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath NS_AVAILABLE_IOS(5_0);
beginUpdates
和endUpdates
兩個方法,在你需要批量處理Cell的時候魁蒜,用來包裹住你的處理代碼囊扳,其他方法名字都很直觀吩翻,不一一介紹了。
最后給大家推薦一個Cocoa框架里的功能強大的類NSFetchedResultsController
锥咸,用于綁定CoreData數(shù)據(jù)和UITableView
或者UICollectionView
狭瞎,直接封裝好所有的UI操作代碼,只要數(shù)據(jù)有變動搏予,UI自動更新熊锭,爽的不要不要的,媽媽再也不用擔(dān)心我的TableView寫不好了雪侥,下一篇文章我準(zhǔn)備詳細(xì)講一講這個有趣的類碗殷。
7、其他補充
編輯模式下速缨,不讓cell縮進(jìn)锌妻,要怎么做呢?
cell.shouldIndentWhileEditing = NO;
或者
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
那一個有效呢旬牲?
注意官方注釋
// Controls whether the background is indented while editing. If not implemented, the default is YES. This is unrelated to the indentation level below. This method only applies to grouped style table views.
只對grouped的TableView有效从祝。