UITableView的代理方法,實現編輯、刪除、排序、多選

weixin_34279579發表於2016-09-29

UITableView除了常規的選擇模式(selection mode)外還有一個編輯模式(editing mode),在編輯模式中可實現刪除,插入,多選,重排序等。

一.進入編輯模式

通過直接設定UITableView的editing屬性或向其傳送setEditing:animated:訊息,可將其置於編輯模式。

self.tableview.editing = YES; [self.tableview setEditing:YES animated:YES];

UIViewController本身也有editing屬性和setEditing:animated:方法,在當前檢視控制器由導航控制器控制且導航欄中包含editButtonItem時,若UIViewController的editing為NO,則顯示為”Edit”,若editing為YES,則顯示為”Done”。

可利用此按鈕在設定UIViewController的editing狀態時同時設定tableView的編輯狀態。

- (void)viewDidLoad {    [super viewDidLoad];    ....

self.navigationItem.rightBarButtonItem = self.editButtonItem; }

-(void)setEditing:(BOOL)editing animated:(BOOL)animated {    [super

setEditing:editing animated:animated];    [self.tableView

setEditing:editing animated:animated]; }

也可自定義其他按鈕,將其響應設為修改tableView進入編輯模式。

- (void)editAction:(id)sender {    [self.tableView setEditing:YES animated:YES]; }

UITableView接收到setEditing:animated:訊息時,會傳送同樣的訊息到所有可見的cell,設定其編輯模式。

二.插入和刪除

進入編輯模式後,UITableView向其DataSource傳送tableView:canEditRowAtIndexPath:訊息詢問每個indexPath是否可編輯,在此方法中對不可以編輯的cell返回NO,可以編輯的cell返回YES,若全部可編輯,可不實現,大部分應用不實現此方法。

-(BOOL)tableView:(UITableView *)tableView

canEditRowAtIndexPath:(NSIndexPath *)indexPath {    if (indexPath.row

== 1) {        return NO;    }    return YES; }

然後,UITableView 向其delegate傳送tableView:editingStyleForRowAtIndexPath:訊息詢問EditingStyle,這裡返回刪除(UITableViewCellEditingStyleDelete)或者插入(UITableViewCellEditingStyleInsert);若不實現此方法,則預設為刪除模式,即UITableViewCellEditingStyleDelete。

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {    return UITableViewCellEditingStyleDelete;    //return UITableViewCellEditingStyleInsert; }

當返回的是UITableViewCellEditingStyleDelete時,所有可編輯的Cell左側都會顯示紅色的”減號”標示;

點選左邊的“減號”,減號會旋轉90度變豎形,並且cell右側出現”Delete”按鈕。

當返回的是UITableViewCellEditingStyleInsert時,在cell的左邊會顯示綠色”加號”按鈕。

當點選”Delete”按鈕或者”加號”按鈕時,UITableView向其DataSource傳送tableView:commitEditingStyle:forRowAtIndexPath:訊息,根據傳遞editingStyle來執行實際的刪除或插入操作,其流程是先修改tableView的資料模型,向其中刪除或插入對應資料項,然後再調整tableView的顯示,刪除或插入對應的cell。

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {    if (editingStyle == UITableViewCellEditingStyleDelete)

{        [dataArray removeObjectAtIndex:indexPath.row];

[tableview deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]

withRowAnimation:UITableViewRowAnimationFade];    }else if(editingStyle == UITableViewCellEditingStyleInsert)

{        [dataArray insertObject:@"new Item"

atIndex:indexPath.row];        [tableview

insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]

withRowAnimation:UITableViewRowAnimationFade];    } }

當要刪除或插入section時,需呼叫deleteSections:withRowAnimation:insertSections:withRowAnimation:方法。

插入刪除流程的方法呼叫時序如圖:

三.重排序

若當前tableView允許重排序,則會在每個cell的右側出現三條灰色橫線的控制元件,拖動此空間可將cell移動到不同的位置。重排序模式和刪除/插入是並行的,即可在顯示重排序空間的同時顯示刪除或插入控制元件。

當tableView的dataSource實現tableView:moveRowAtIndexPath:toIndexPath:方法後,tableView進入編輯模式後就會在右側顯示“重排序”控制元件,如圖所示。

其訊息處理流程為:

tableView收到setEditing:animated:訊息並將同樣的訊息傳送給可見的cell。

tableView向其DataSource傳送tableView:canMoveRowAtIndexPath:訊息,詢問每一行是否可顯示重排序空間,若為NO,則不顯示,若為YES則顯示。此方法不實現時預設所有行都可顯示重排序控制元件。這時就會在每一行的右側顯示重排序控制元件。

因為重排序沒有使用向delegate傳送tableView:editingStyleForRowAtIndexPath:訊息詢問編輯模式,所以其 與刪除、插入控制元件可同時存在,在一般情況下不應該同時出現,所以應實現了 tableView:editingStyleForRowAtIndexPath:並返回 UITableViewCellEditingStyleNone;若不實現 tableView:editingStyleForRowAtIndexPath:則會預設使用刪除模式,即右側出現“排序”控制元件時,左側會出現”刪 除”控制元件。

使用者可拖動每行右側的空間來移動該行的位置。

使用者拖動某行經過目標行上方時,tableView會向delegate傳送tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:(若delegate有實現)訊息詢問是否可移動到此位置(ProposedIndexPath),若不可移動到此位置則返回一個新的目的indexPath,可以的話直接將ProposedIndexPath返回即可。一般情況下不需實現此方法。

-(NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {    if (proposedDestinationIndexPath.row == 5) {        return [NSIndexPath indexPathForRow:8 inSection:0];      }    return proposedDestinationIndexPath; }

tableView向其DataSource傳送tableView:moveRowAtIndexPath:toIndexPath:訊息,在此方法中更改tableView的資料模型,移動裡面資料項的位置。

- (void)tableView:(UITableView *)tableView

moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath

toIndexPath:(NSIndexPath *)destinationIndexPath{    if(sourceIndexPath

== destinationIndexPath)        return;    id object = [dataArray

objectAtIndex:sourceIndexPath.row];    [dataArray

removeObjectAtIndex:sourceIndexPath.row];      [dataArray

insertObject:object atIndex:destinationIndexPath.row]; }

總體訊息流程為:

四.Swipe to Delete

當使用者在tableView的一行上滑動時,會在右側直接出現刪除按鈕,點選刪除按鈕可刪除此行。啟用Swipe to Delete模式的條件時tableView的DataSource實現了tableView:commitEditingStyle:forRowAtIndexPath:方法;在iOS5中還要保證tableView的allowsMultipleSelectionDuringEditing屬性不為YES(見後面解釋)。

滿足上述條件後,當使用者在tableView的行上滑動時,tableView會向自身傳送setEditing:animated:訊息進入編 輯模式,同時向可見的cell傳送setEditing:animated:訊息,在當前滑動的行右側會出現紅色”Delete”按鈕。

同樣在點選”Delete”按鈕時會向tableView的DataSource傳送tableView:commitEditingStyle:forRowAtIndexPath:訊息,執行實際的刪除操作。

“Delete”按鈕上顯示的文字可以更改,包括普通刪除模式下的”Delete”按鈕。若要顯示不同的內容,可在tableView Delegate中實現tableView:titleForDeleteConfirmationButtonForRowAtIndexPath:方法,返回”Delete”按鈕中需要顯示的內容

tableView在向自身傳送setEditing:animated:訊息的前後,會向其delegate分別傳送tableView:willBeginEditingRowAtIndexPath:,tableView:didEndEditingRowAtIndexPath:訊息。在這些方法中可相應更新tableView的顯示。How does the Twitter iPhone app implement side swiping on a table?中通過實現tableView:willBeginEditingRowAtIndexPath:方法使得使用者在tableView的行上swipe時可滑出選單。

五.多行選取模式

在iphone自帶的郵件程式中,點選編輯按鈕後會出現使用”紅勾”多選的效果,如圖所示

有幾種方法可以實現這種效果

1.蘋果公共API

在iOS5.0中UITableView增加了allowsMultipleSelectionDuringEditing屬性和indexPathsForSelectedRows方 法,allowsMultipleSelectionDuringEditing屬性預設為NO,當此值為YES時,UITableView進入編輯模式 不會向dataSource查詢editStyle,而會直接每個Cell的左邊顯示圓形選擇框,點選選擇該行後圓形框裡面為對勾。可使用 indexPathsForSelectedRows方法獲取到所有選擇行的indexPath。

蘋果公司提供了使用此種方式的例項程式碼:TableMultiSelect

注:當allowsMultipleSelectionDuringEditing屬性為YES時,不管當前在不在編輯模式內,swipe to delete都不起作用,若要同時使用swipe to delete,需在完成選擇任務後,將tableView的allowsMultipleSelectionDuringEditing恢復為NO。另 外,多選”控制元件可與”重排序”控制元件同時出現。

2.蘋果私用API

在iOS5之前,蘋果並沒有提供多行選取的API,但其內部確實實現了,我們可以通過使用私有API實現。

tableView:editingStyleForRowAtIndexPath:方 法中若返回的是 UITableViewCellEditingStyleDelete|UITableViewCellEditingStyleInsert則可以進入 多選模式,效果同allowsMultipleSelectionDuringEditing設為YES時相同。這也是“多選”控制元件不會與“插入”控 件,”刪除”控制元件同時出現,卻可以和”重排序”控制元件同時存在的原因。

獲取到選擇的行時,同樣可以使用私有方法indexPathsForSelectedRows獲取,或者使用公開的tableView:didSelectRowAtIndexPath:,tableView:didDeselectRowAtIndexPath:方法在選擇/取消選擇時逐個獲取並儲存。

注:以上兩種方式均需保證UITableViewCellselectionStyle屬性不為UITableViewCellSelectionStyleNone,否則選擇後的“紅勾”無法顯示。

3.完全定製方法

一些文章中介紹了不使用tableView本身的方法而完全自己定製實現多選效果的方法。

如:Table View Multi-Row Edit Mode

Multiple row selection and editing in a UITableView

參考:

Table View Programming Guide for iOS – Inserting and Deleting Rows and Sections

Table View Programming Guide for iOS – Managing the Reordering of Rows

UITableView Class Reference

UITableViewDelegate Protocol Reference

UITableViewDataSource Protocol Reference

UITableViewCell Class Reference

How does the Twitter iPhone app implement side swiping on a table?

UITableView划動刪除的實現

UITableView多選刪除,類似mail中的多選刪除效果

iPhone開發技巧之私有API(2)— UITableView

iOS 5 Dev Warning: UITableView’s Multiple Select During Editing Doesn’t Work with Swipe to Delete

Table View Multi-Row Edit Mode

Multiple row selection and editing in a UITableView

http://linglong117.blog.163.com/blog/static/277145472012103075527791/

相關文章