iOS UIKit:TableView之編輯模式(3)

      通常table view有編輯模式和正常模式,當table view進入編輯模式時,會在row的左邊顯示編輯重排控件,如圖 42所示的編輯模式時的控件佈局;左邊的editing control有表 61的兩種圖標。 html

表 61 table view編輯控件 數組

圖標app

描述ide

Deletion控件佈局

Insertion控件動畫

 

      若table view在編輯模式時,用戶點擊編輯控件,那麼table view會發送一系列消息給data source 和delegate對象。能夠經過實現這些方法來修改table view的外觀和行爲,或者執行插入和刪除操做。  ui

1 插入與刪除row spa

      UITableView中有兩個編輯row的方法:插入刪除在任什麼時候候均可直接調用這兩個方法,無需在tableView進入編輯模式才能調用。而且當調用這兩方法後,tableView會自動從新加載(reload)。 3d

- (void)deleteRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPathscode

                   withRowAnimation:(UITableViewRowAnimation)animation

- (void)insertRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths 

                         withRowAnimation:(UITableViewRowAnimation)animation

參數語義:

            indexPaths:但願修改的rows路徑,是一個路徑對象的數組;

            animation:爲動畫類型。

注意:

        這兩個方法的調用須要相應修改tableview中顯示的數據模型,即應保持data source的三個方法(section數、row數和cell對象)返回的數據與修改後的數據一致。如調用方法刪除某一行,那麼該行就不能在tableview中再顯示,不然會奔潰出錯。

1.1 進入編輯模式

       當tableView進入編輯模式時,即在每一個row的左邊會出現插入或刪除控件。其中能夠經過UITableView的setEditing:animated:方法來控制其進入和退出編輯模式。

- (void)setEditing:(BOOL)editing    animated:(BOOL)animate

參數語義:

                  editing:控制進出操做,若爲YES爲進入編輯模式;若爲NO爲退出編輯模式。

                  animate:爲設置是否進行動畫播放。

 

      當調用了setEditing方法以後,tableView會陸續調用data source和delegate的幾個方法,具體執行次序如圖 61所示。

      1) tableView對象首先調用data source對象的tableView:canEditRowAtIndexPath:方法(可選);

      2) 而後tableView對象首先調用delegate對象的tableView:editingStyleForRowAtIndexPath:方法(必選)該方法返回row所要顯示的控件類型,即刪除或插入控件。

      3) 接着,在table view中的row左邊會顯示響應的控件,此時用戶能夠進行操做;

     4)當用戶對row的編輯控件進行點擊時,會調用data source對象的tableView:commitEditingStyle:forRowAtIndexPath:方法(必選)用戶便可實現該方法,從而實現但願完成的操做,如刪除或添加某一row。

 

圖 61 Calling sequence for inserting or deleting rows in a table view

1.2 操做示例

1)tableView初始化

      首先初始化一個數組來顯示table view中的cell,並在導航欄右邊添加一個進入編輯模式的按鈕,該按鈕爲UITableView對象提供的控制項

 1 @interface ViewController : UITableViewController
 2 @property NSMutableArray * array;
 3 @end
 4 @implementation ViewController
 5 - ( void)viewDidLoad {
 6     [super viewDidLoad];
 7 self.navigationItem.rightBarButtonItem = self.editButtonItem;
 8 
 9     _array = [[NSMutableArray alloc] initWithObjects:
10                 [NSMutableArray arrayWithObjects: @" Item1 "@" Item2 ", nil],
11                 [NSMutableArray arrayWithObjects: @" Item1 "@" Item2 "@" Item3 ", nil],
12                 [NSMutableArray arrayWithObjects: @" Item1 "@" Item2 "@" Item3 "@" Item4 ", nil],
13                 [NSMutableArray arrayWithObjects: @" Item1 "@" Item2 "@" Item3 "@" Item4 "@" Item5 ",nil],
14                 nil];
15 }
16 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
17 {
18      return [_array count];
19 }
20 -(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
21 {
22      return [_array[section] count];
23 }
24 -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
25 {
26     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:  @" myCell "];  
27      return cell;
28 }

 

2) 進入編輯模式

      當用戶點擊導航按鈕時,將會自動調用以下實現的setEditing方法,在該方法中調用tableView對象的setEditing方法進入編輯模式;而後在第二個方法中將每一個section中的奇數row顯示插入控件,偶數的row顯示爲刪除控件;

 1 - ( void)setEditing:(BOOL)editing animated:(BOOL)animated {
 2     [super setEditing:editing animated:animated];
 3     [self.tableView setEditing:editing animated:YES];
 4 }
 5 - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
 6      if (indexPath.row % 2 ==  1) {
 7          return UITableViewCellEditingStyleInsert;
 8     }  else {
 9          return UITableViewCellEditingStyleDelete;
10     }
11 }

 

3) 響應操做

      當用戶點擊編輯控件時,執行以下方法,從而在該方法中判斷是什麼類型(插入或刪除操做);接着執行對array數組執行不一樣的操做,最終經過調用tableview的deleteRowsAtIndexPaths方法和insertRowsAtIndexPaths方法來刷新表格的內容。

 1 - ( void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
 2 
 3     if (editingStyle == UITableViewCellEditingStyleDelete) {  // 如果刪除操做,則刪除數組內容,並刷新表格
 4          [_array[indexPath.section] removeObjectAtIndex:indexPath.row];
 5         [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
 6     }
 7      else   // 如果插入操做,則添加一個數組元素,並刷新表格
 8      {
 9         [_array[indexPath.section] insertObject:  @" hlw " atIndex:indexPath.row];
10         [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
11 }
12 }

 

4) 顯示效果

      如影 61所示是表格的顯示效果,和刪除操做視頻。

影 61 刪除操做效果圖(雙擊)

 

2 批量操做

      除了能夠對row進行編輯,UITableView還支持對section進行編輯,而且能夠一次性進行插入、刪除和重載等多個操做。以下所示是UITableView總共提供了8個方法:

- (void)beginUpdates;

- (void)endUpdates;

- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;

- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;

- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;

- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation (UITableViewRowAnimation)animation;

- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation: (UITableViewRowAnimation)animation;

- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;

      其中對row和section的6個操做方法必須處於beginUpdatesendUpdates兩方法之間調用。

以下的示例,當用戶點擊某行時,就添加和刪除幾行:

 1 - ( void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
 2 {
 3     [_array[ 2] removeObjectAtIndex: 0];
 4     [_array[ 1] removeObjectAtIndex: 0];
 5     [_array[ 0] insertObject:  @" hlw " atIndex: 0];
 6     [_array[ 3] insertObject:  @" hlw " atIndex: 0];
 7     NSArray *deleteIndexPaths = [NSArray arrayWithObjects:
 8                                  [NSIndexPath indexPathForRow: 0 inSection: 2],
 9                                  [NSIndexPath indexPathForRow: 0 inSection: 1],
10                                  nil];
11     NSArray *insertIndexPaths = [NSArray arrayWithObjects:
12                                  [NSIndexPath indexPathForRow: 0 inSection: 0],
13                                  [NSIndexPath indexPathForRow: 0 inSection: 3],
14                                  nil];
15 
16     UITableView *tv = self.tableView;
17     [tv beginUpdates];
18     [tv deleteRowsAtIndexPaths:deleteIndexPaths withRowAnimation:UITableViewRowAnimationFade];
19     [tv insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationRight];
20     [tv endUpdates];
21 }
注意:

    上述對_array的操做順序能夠與調用tv的順序不同,其中動畫的展現效果是按tv的調用順序執行。

 

3 交換操做

      UITableView提供了一個方法可以交互兩row或兩section的順序,從而實現從新排序的效果,這兩個方法可以在任何狀況下使用,並非必須進入編輯模式才能使用。

- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath  toIndexPath:(NSIndexPath *)newIndexPath

- (void)moveSection:(NSInteger)sectiontoSection:(NSInteger)newSection

注意:

       moveRowAtIndexPath方法能夠交換任意的兩row;但moveSection只能交換兩個section有相同數量的row

 

以下所示,當用戶點擊任何一行時,即與下一行交換:

1 - ( void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
2 {
3     NSIndexPath * to = [NSIndexPath indexPathForRow:indexPath.row+ 1 inSection:indexPath.section];
4     [tableView moveRowAtIndexPath:indexPath toIndexPath:to];
5 }

 

3.1 進入編輯模式

      與刪除和插入row類型,當table view進入編輯模式,即調用了setEditing方法以後,tableView會陸續調用data source和delegate的幾個方法,具體執行次序如圖 62所示。

      1) tableView對象首先調用data source對象的tableView:canMoveRowAtIndexPath:方法(必選)若是該方法返回YES,則在cell的右邊會顯示一個可交換的控件。

      2) 當在cell中出現交換控件後,用戶便可拖拽交換row。

      3) 若當用戶拖拽了row後,那麼tableView對象會去調用delegate對象的tableView:targetIndexPathForMoveFromRowAtIndexPath方法(可選)

   4) 接着,table view對象會去調用data source對象tableView:moveRowAtIndexPath:toIndexPath:方法(必選)這個方法會自動交換拖拽的兩行,不須要調用   UITableView的moveRowAtIndexPath方法便可進行交換。

 

 

圖 62 Calling sequence for reordering a row in a table view

 

3.2 操做示例

      如在6.1.2小節所示的示例基礎之上進行操做,不容許每一個section的第0行進行交換,而其它方法是能夠交換的,以下是實現的兩個方法:

 1 - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
 2      if (indexPath.row ==  0) {
 3          return NO;
 4     }
 5      return YES;
 6 }
 7 - ( void)tableView:(UITableView *)tableView
 8 moveRowAtIndexPath:(NSIndexPath *)fromIndexPath
 9       toIndexPath:(NSIndexPath *)toIndexPath
10 {
11     
12 }

      如影 62所示展現的顯示效果,其與插入和刪除操做不會衝突,都可以顯示。

 

影 62 交換row效果圖

 

4 自定義editingAccessoryView

4.1 修改附加視圖

      當進入編輯模式時,cell右邊還有一個附件視圖的位置,默認狀況爲空,用戶可使用標準視圖或者自定義視圖內容,只需修改UITableViewCell對象的editingAccessoryView屬性,同時還能夠修改刪除按鈕的顯示內容其由tableView:titleForDeleteConfirmationButtonForRowAtIndexPath方法決定顯示的內容:

-(NSString*)tableView:(UITableView*)tableViewtitleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath

返回參數:

            爲所要顯示的標題內容。

 

以下所示,當進入編輯模式時,顯示附件視圖並修改刪除按鈕的內容:

 1 -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 2 {
 3     UILabel *mainLabel;
 4     mainLabel = [[UILabel alloc] initWithFrame:CGRectMake( 0.00.050.015.0)];
 5     mainLabel.text = _array[indexPath.section][indexPath.row];
 6 
 7      static NSString *CellIdentifier =  @" myCell ";
 8     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
 9     
10     [cell setEditingAccessoryView:mainLabel];
11  //     cell.editingAccessoryView = mainLabel;  // 或者直接賦值
12     
13      return cell;
14 }
15 - (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
16 {
17      return  @" myDelete ";
18 }

 

圖 63 編輯模式自定義accessoryView效果圖

 

4.2 修改刪除按鈕

      對於那些支持刪除操做的cell,當在編輯模式中點擊左邊的刪除控件,會在右邊出現有一個刪除按鈕;或者在正常模式下,水平滑動也能出現這個刪除按鈕,當點擊這個刪除按鈕後,會調用data source對象的tableView:commitEditingStyle:方法(如6.1.1小節所示)。

UITableView支持修改上述這個刪除按鈕和相應響應方法,即用戶能夠實現UITableViewDelegate協議的tableView:editActionsForRowAtIndexPath方法來自定義顯示內容響應方法,該方法的定義爲:

-(NSArray<UITableViewRowAction*>*)tableView:(UITableView*)tableView     //UITableViewDelegate協議方法

                       editActionsForRowAtIndexPath:(NSIndexPath *)indexPath

+ (instancetype)rowActionWithStyle:(UITableViewRowActionStyle)style //UITableViewRowAction類的便利方法

                                           title:(NSString *)title

                                       handler:(void (^)(UITableViewRowAction *action, NSIndexPath *indexPath))handler

rowActionWithStyle方法參數語義:

                                           style:爲顯示的類型;

                                           title:爲顯示的標題;

                                           handler:爲響應的block。

      以下所示,建立兩個按鈕來替換系統默認的刪除按鈕,當用戶水平滑動時,出現兩個按鈕,當點擊時執行相應的block。

 1 - (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView
 2                   editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
 3 {
 4     UITableViewRowAction *first = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title: @" first " handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
 5         NSLog( @" UITableViewRowAction action first ");
 6     }];
 7     UITableViewRowAction *second = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title: @" second " handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
 8         NSLog( @" UITableViewRowAction action second ");
 9     }];
10     
11     NSArray * array =[[NSArray alloc] initWithObjects:first, second, nil];
12     
13      return array;
14 }

 

 

影 63 效果圖

      其中上述的itemX爲附加視圖的內容,而first和second按鈕爲修改的內容。

 

5 參考文獻

       [1] Table View Programming Guide for IOS

相關文章
相關標籤/搜索