UITableView 編輯模式詳解
UITableView
的相關(guān)編輯操作非常全炊豪,今天我們來做一個總結(jié)在跳。跟編輯相關(guān)的屬性和接口有如下,我們一個一個分析伶选,我們先認真閱讀一下相關(guān)頭文件史飞,我根據(jù)意思大概翻譯了一下注釋尖昏。
屬性方法
@property (nonatomic, getter=isEditing) BOOL editing;
// 默認狀態(tài)是非編輯狀態(tài),如果不調(diào)用下面接口直接設(shè)置构资,是沒有動畫的
- (void)setEditing:(BOOL)editing animated:(BOOL)animated;
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;
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是否需要縮進。
- (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;
編輯狀態(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 多選模式趟咆,左邊是藍色對號
特別注意添瓷,右邊的移動并不是這里控制的,需要實現(xiàn)下面這個回調(diào)才會出現(xiàn)忍啸。
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;
另外對于新手來說仰坦,要明白這里的回調(diào)都沒有對UI和數(shù)據(jù)進行操作,開發(fā)者需要在回調(diào)中计雌,完成相應(yīng)的操作悄晃。比如刪除或者添加一條數(shù)據(jù),應(yīng)在
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
上面這個回調(diào)中,根據(jù)editingStyle進行判斷妈橄,處理對應(yīng)的UI和數(shù)據(jù)庶近。
數(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寫不好了碟案,下一篇文章我準備詳細講一講這個有趣的類。
2017.11.29更新
感謝簡單程序媛
同學(xué)的發(fā)問洞焙,在此補充一個回調(diào)蟆淀,用于只使用tableView右側(cè)排序功能,而不顯示左側(cè)刪除和插入澡匪,并且左側(cè)不留白的方法
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewCellEditingStyleNone;
}
- (BOOL)tableView:(UITableView *)tableview shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
UITableViewCellEditingStyleNone
隱藏了左側(cè)編輯按鈕,shouldIndentWhileEditingRowAtIndexPath控制cell在編輯模式下左側(cè)是否縮進褒链。