UITableView編輯模式詳解

轉載:UITableView 編輯模式詳解
作者:秋刀生魚片

UITableView的相關編輯操作非常全,今天我們來做一個總結。跟編輯相關的屬性和接口有如下,我們一個一個分析,我們先認真閱讀一下相關頭文件,我根據意思大概翻譯了一下注釋。

1、屬性方法

@property (nonatomic, getter=isEditing) BOOL editing;                             

// 默認狀態是非編輯狀態,如果不調用下面接口直接設置,是沒有動畫的
- (void)setEditing:(BOOL)editing animated:(BOOL)animated;

2、DataSource

// 當增減按鈕按下時,用來處理數據和UI的回調。
// 8.0版本后加入的UITableViewRowAction不在這個回調的控制范圍內,UITableViewRowAction有單獨的回調Block。
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;

// 這個回調實現了以后,就會出現更換位置的按鈕,回調本身用來處理更換位置后的數據交換。
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;

// 這個回調決定了在當前indexPath的Cell是否可以編輯。
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;

// 這個回調決定了在當前indexPath的Cell是否可以移動。
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;

3、Delegate

// 這個回調很關鍵,返回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后側滑菜單的新接口,支持多個側滑按鈕。
- (nullable NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(8_0) __TVOS_PROHIBITED;

// 這個接口決定編輯狀態下的Cell是否需要縮進。
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath;

// 這是兩個狀態回調
- (void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath __TVOS_PROHIBITED;
- (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath __TVOS_PROHIBITED;

4、編輯狀態

UITableView 通過editing屬性控制編輯狀態,調用- (void)setEditing:(BOOL)editing animated:(BOOL)animated接口,可以決定是否使用原生的變換動畫。

當調用這個接口,并將editing設為YES是,UITableView將開始詢問代理(Delegate)需要編輯哪些Cell,用什么樣的方式編輯。

首先調用回調方法- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;,這里需要返回YES

然后依次為各個Cell調用- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;方法獲取編輯樣式。

typedef NS_ENUM(NSInteger, UITableViewCellEditingStyle) {
    UITableViewCellEditingStyleNone,
    UITableViewCellEditingStyleDelete,
    UITableViewCellEditingStyleInsert
};

編輯樣式枚舉有三種,位運算組合則由不同的用途。

UITableViewCellEditingStyleNone 沒有編輯樣式
UITableViewCellEditingStyleDelete 刪除樣式 (左邊是紅色減號)
UITableViewCellEditingStyleInsert 插入樣式  (左邊是綠色加號)
UITableViewCellEditingStyleDelete|UITableViewCellEditingStyleInsert 多選模式,左邊是藍色對號

特別注意,右邊的移動并不是這里控制的,需要實現下面這個回調才會出現。

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;

另外對于新手來說,要明白這里的回調都沒有對UI和數據進行操作,開發者需要在回調中,完成相應的操作。比如刪除或者添加一條數據,應在

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;

上面這個回調中,根據editingStyle進行判斷,處理對應的UI和數據。

5、8.0版本后的多選側滑菜單

8.0版本后,短信等原生應用都有了側滑多按鈕選擇,原來是蘋果的前端團隊為TableView加入相關接口,這里給個例子

- (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、數據與UI更新

數據更新沒什么好說的,直接操作數據容器就好,無論是數組、字典還是CoreData數據。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);

beginUpdatesendUpdates兩個方法,在你需要批量處理Cell的時候,用來包裹住你的處理代碼,其他方法名字都很直觀,不一一介紹了。

最后給大家推薦一個Cocoa框架里的功能強大的類NSFetchedResultsController,用于綁定CoreData數據和UITableView或者UICollectionView,直接封裝好所有的UI操作代碼,只要數據有變動,UI自動更新,爽的不要不要的,媽媽再也不用擔心我的TableView寫不好了,下一篇文章我準備詳細講一講這個有趣的類。

7、其他補充

編輯模式下,不讓cell縮進,要怎么做呢?

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有效。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容