UITableView除了常規(guī)的選擇模式(selection mode)外還有一個(gè)編輯模式(editing mode),在編輯模式中可實(shí)現(xiàn)刪除旱捧,插入独郎,多選,重排序等枚赡。
一.進(jìn)入編輯模式
通過直接設(shè)置UITableView的editing屬性或向其發(fā)送setEditing:animated:消息氓癌,可將其置于編輯模式。
self.tableview.editing = YES; [self.tableview setEditing:YES animated:YES];
UIViewController本身也有editing屬性和setEditing:animated:方法贫橙,在當(dāng)前視圖控制器由導(dǎo)航控制器控制且導(dǎo)航欄中包含editButtonItem時(shí)贪婉,若UIViewController的editing為NO,則顯示為”Edit”,若editing為YES,則顯示為”Done”料皇。
可利用此按鈕在設(shè)置UIViewController的editing狀態(tài)時(shí)同時(shí)設(shè)置tableView的編輯狀態(tài)谓松。
- (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]; }
也可自定義其他按鈕,將其響應(yīng)設(shè)為修改tableView進(jìn)入編輯模式。
- (void)editAction:(id)sender {? ? [self.tableView setEditing:YES animated:YES]; }
UITableView接收到setEditing:animated:消息時(shí)践剂,會(huì)發(fā)送同樣的消息到所有可見的cell,設(shè)置其編輯模式娜膘。
二.插入和刪除
進(jìn)入編輯模式后逊脯,UITableView向其DataSource發(fā)送tableView:canEditRowAtIndexPath:消息詢問每個(gè)indexPath是否可編輯,在此方法中對不可以編輯的cell返回NO,可以編輯的cell返回YES,若全部可編輯竣贪,可不實(shí)現(xiàn),大部分應(yīng)用不實(shí)現(xiàn)此方法军洼。
-(BOOL)tableView:(UITableView *)tableView
canEditRowAtIndexPath:(NSIndexPath *)indexPath {? ? if (indexPath.row
== 1) {? ? ? ? return NO;? ? }? ? return YES; }
然后巩螃,UITableView 向其delegate發(fā)送tableView:editingStyleForRowAtIndexPath:消息詢問EditingStyle,這里返回刪除(UITableViewCellEditingStyleDelete)或者插入(UITableViewCellEditingStyleInsert);若不實(shí)現(xiàn)此方法匕争,則默認(rèn)為刪除模式避乏,即UITableViewCellEditingStyleDelete。
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {? ? return UITableViewCellEditingStyleDelete;? ? //return UITableViewCellEditingStyleInsert; }
當(dāng)返回的是UITableViewCellEditingStyleDelete時(shí)甘桑,所有可編輯的Cell左側(cè)都會(huì)顯示紅色的”減號”標(biāo)示;
點(diǎn)擊左邊的“減號”,減號會(huì)旋轉(zhuǎn)90度變豎形拍皮,并且cell右側(cè)出現(xiàn)”Delete”按鈕。
當(dāng)返回的是UITableViewCellEditingStyleInsert時(shí)跑杭,在cell的左邊會(huì)顯示綠色”加號”按鈕铆帽。
當(dāng)點(diǎn)擊”Delete”按鈕或者”加號”按鈕時(shí),UITableView向其DataSource發(fā)送tableView:commitEditingStyle:forRowAtIndexPath:消息德谅,根據(jù)傳遞editingStyle來執(zhí)行實(shí)際的刪除或插入操作爹橱,其流程是先修改tableView的數(shù)據(jù)模型,向其中刪除或插入對應(yīng)數(shù)據(jù)項(xiàng),然后再調(diào)整tableView的顯示,刪除或插入對應(yīng)的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];? ? } }
當(dāng)要?jiǎng)h除或插入section時(shí)愧驱,需調(diào)用deleteSections:withRowAnimation:或insertSections:withRowAnimation:方法。
插入刪除流程的方法調(diào)用時(shí)序如圖:
三.重排序
若當(dāng)前tableView允許重排序椭盏,則會(huì)在每個(gè)cell的右側(cè)出現(xiàn)三條灰色橫線的控件组砚,拖動(dòng)此空間可將cell移動(dòng)到不同的位置。重排序模式和刪除/插入是并行的庸汗,即可在顯示重排序空間的同時(shí)顯示刪除或插入控件惫确。
當(dāng)tableView的dataSource實(shí)現(xiàn)tableView:moveRowAtIndexPath:toIndexPath:方法后,tableView進(jìn)入編輯模式后就會(huì)在右側(cè)顯示“重排序”控件,如圖所示蚯舱。
其消息處理流程為:
tableView收到setEditing:animated:消息并將同樣的消息發(fā)送給可見的cell改化。
tableView向其DataSource發(fā)送tableView:canMoveRowAtIndexPath:消息,詢問每一行是否可顯示重排序空間枉昏,若為NO,則不顯示陈肛,若為YES則顯示。此方法不實(shí)現(xiàn)時(shí)默認(rèn)所有行都可顯示重排序控件兄裂。這時(shí)就會(huì)在每一行的右側(cè)顯示重排序控件句旱。
因?yàn)橹嘏判驔]有使用向delegate發(fā)送tableView:editingStyleForRowAtIndexPath:消息詢問編輯模式,所以其 與刪除晰奖、插入控件可同時(shí)存在谈撒,在一般情況下不應(yīng)該同時(shí)出現(xiàn),所以應(yīng)實(shí)現(xiàn)了 tableView:editingStyleForRowAtIndexPath:并返回 UITableViewCellEditingStyleNone匾南;若不實(shí)現(xiàn) tableView:editingStyleForRowAtIndexPath:則會(huì)默認(rèn)使用刪除模式啃匿,即右側(cè)出現(xiàn)“排序”控件時(shí),左側(cè)會(huì)出現(xiàn)”刪 除”控件。
用戶可拖動(dòng)每行右側(cè)的空間來移動(dòng)該行的位置溯乒。
用戶拖動(dòng)某行經(jīng)過目標(biāo)行上方時(shí)夹厌,tableView會(huì)向delegate發(fā)送tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:(若delegate有實(shí)現(xiàn))消息詢問是否可移動(dòng)到此位置(ProposedIndexPath),若不可移動(dòng)到此位置則返回一個(gè)新的目的indexPath,可以的話直接將ProposedIndexPath返回即可裆悄。一般情況下不需實(shí)現(xiàn)此方法矛纹。
-(NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {? ? if (proposedDestinationIndexPath.row == 5) {? ? ? ? return [NSIndexPath indexPathForRow:8 inSection:0];? ? ? }? ? return proposedDestinationIndexPath; }
tableView向其DataSource發(fā)送tableView:moveRowAtIndexPath:toIndexPath:消息,在此方法中更改tableView的數(shù)據(jù)模型,移動(dòng)里面數(shù)據(jù)項(xiàng)的位置光稼。
- (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
當(dāng)用戶在tableView的一行上滑動(dòng)時(shí)或南,會(huì)在右側(cè)直接出現(xiàn)刪除按鈕,點(diǎn)擊刪除按鈕可刪除此行钟哥。啟用Swipe to Delete模式的條件時(shí)tableView的DataSource實(shí)現(xiàn)了tableView:commitEditingStyle:forRowAtIndexPath:方法迎献;在iOS5中還要保證tableView的allowsMultipleSelectionDuringEditing屬性不為YES(見后面解釋)。
滿足上述條件后腻贰,當(dāng)用戶在tableView的行上滑動(dòng)時(shí)吁恍,tableView會(huì)向自身發(fā)送setEditing:animated:消息進(jìn)入編 輯模式,同時(shí)向可見的cell發(fā)送setEditing:animated:消息播演,在當(dāng)前滑動(dòng)的行右側(cè)會(huì)出現(xiàn)紅色”Delete”按鈕冀瓦。
同樣在點(diǎn)擊”Delete”按鈕時(shí)會(huì)向tableView的DataSource發(fā)送tableView:commitEditingStyle:forRowAtIndexPath:消息,執(zhí)行實(shí)際的刪除操作。
“Delete”按鈕上顯示的文字可以更改写烤,包括普通刪除模式下的”Delete”按鈕翼闽。若要顯示不同的內(nèi)容,可在tableView Delegate中實(shí)現(xiàn)tableView:titleForDeleteConfirmationButtonForRowAtIndexPath:方法洲炊,返回”Delete”按鈕中需要顯示的內(nèi)容
tableView在向自身發(fā)送setEditing:animated:消息的前后感局,會(huì)向其delegate分別發(fā)送tableView:willBeginEditingRowAtIndexPath:,tableView:didEndEditingRowAtIndexPath:消息。在這些方法中可相應(yīng)更新tableView的顯示暂衡。How does the Twitter iPhone app implement side swiping on a table?中通過實(shí)現(xiàn)tableView:willBeginEditingRowAtIndexPath:方法使得用戶在tableView的行上swipe時(shí)可滑出菜單询微。
五.多行選取模式
在iphone自帶的郵件程序中,點(diǎn)擊編輯按鈕后會(huì)出現(xiàn)使用”紅勾”多選的效果狂巢,如圖所示
有幾種方法可以實(shí)現(xiàn)這種效果
1.蘋果公共API
在iOS5.0中UITableView增加了allowsMultipleSelectionDuringEditing屬性和indexPathsForSelectedRows方 法撑毛,allowsMultipleSelectionDuringEditing屬性默認(rèn)為NO,當(dāng)此值為YES時(shí),UITableView進(jìn)入編輯模式 不會(huì)向dataSource查詢editStyle,而會(huì)直接每個(gè)Cell的左邊顯示圓形選擇框唧领,點(diǎn)擊選擇該行后圓形框里面為對勾藻雌。可使用 indexPathsForSelectedRows方法獲取到所有選擇行的indexPath斩个。
蘋果公司提供了使用此種方式的實(shí)例代碼:TableMultiSelect
注:當(dāng)allowsMultipleSelectionDuringEditing屬性為YES時(shí)胯杭,不管當(dāng)前在不在編輯模式內(nèi),swipe to delete都不起作用,若要同時(shí)使用swipe to delete,需在完成選擇任務(wù)后受啥,將tableView的allowsMultipleSelectionDuringEditing恢復(fù)為NO歉摧。另 外,多選”控件可與”重排序”控件同時(shí)出現(xiàn)腔呜。
2.蘋果私用API
在iOS5之前叁温,蘋果并沒有提供多行選取的API,但其內(nèi)部確實(shí)實(shí)現(xiàn)了,我們可以通過使用私有API實(shí)現(xiàn)核畴。
在tableView:editingStyleForRowAtIndexPath:方 法中若返回的是 UITableViewCellEditingStyleDelete|UITableViewCellEditingStyleInsert則可以進(jìn)入 多選模式膝但,效果同allowsMultipleSelectionDuringEditing設(shè)為YES時(shí)相同。這也是“多選”控件不會(huì)與“插入”控 件,”刪除”控件同時(shí)出現(xiàn)谤草,卻可以和”重排序”控件同時(shí)存在的原因跟束。
獲取到選擇的行時(shí),同樣可以使用私有方法indexPathsForSelectedRows獲取丑孩,或者使用公開的tableView:didSelectRowAtIndexPath:,tableView:didDeselectRowAtIndexPath:方法在選擇/取消選擇時(shí)逐個(gè)獲取并保存冀宴。
注:以上兩種方式均需保證UITableViewCell的selectionStyle屬性不為UITableViewCellSelectionStyleNone,否則選擇后的“紅勾”無法顯示。
3.完全定制方法
一些文章中介紹了不使用tableView本身的方法而完全自己定制實(shí)現(xiàn)多選效果的方法温学。
如: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
UITableViewDelegate Protocol Reference
UITableViewDataSource Protocol Reference
UITableViewCell Class Reference
How does the Twitter iPhone app implement side swiping on a table?
UITableView劃動(dòng)刪除的實(shí)現(xiàn)
UITableView多選刪除,類似mail中的多選刪除效果
iPhone開發(fā)技巧之私有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/