一、總述
在iOS開發(fā)中,UITableView的使用率可以說是非常高的,所以它在iOS開發(fā)中的地位是無法替代的。最近項(xiàng)目涉及到UITableView的編輯問題,這個(gè)問題其實(shí)非常廣泛,我希望從我的角度盡可能地把這個(gè)問題思慮全面,講述清楚。
UITableView的編輯,我主要從這些方面來講述:cell的插入,刪除,選擇,移動(dòng)排序以及UITableView的編輯模式等。
二、UITableView cell的插入
UITableView cell的插入首先要保證UITableView的數(shù)據(jù)源插入了數(shù)據(jù),否則會(huì)發(fā)生奔潰。正確地插入了數(shù)據(jù)之后,可以通過一下幾種方式達(dá)到插入Cell的效果:
1.刷新UITableView,既調(diào)用UITableView的-reloadData:方法或者-reloadSections: withRowAnimation:方法,其實(shí)還有其他的一些刷新UITableView的方式。但是我要說的是使用這種方式的話性能方面不是很好,因?yàn)樗⑿耈ITableView會(huì)調(diào)用很多次代理方法。
2.直接插入Cell,既調(diào)用UITableView的insertRowsAtIndexPaths:withRowAnimation:方法或者insertSections: withRowAnimation:方法來插入。這種方式相對(duì)性能較高。
需要注意的問題:插入了Cell最好還是調(diào)用一下UITableView的-scrollToRowAtIndexPath:atScrollPosition:UITableViewScrollPositionNoneanimated:這個(gè)方法,把UITableView滾動(dòng)到對(duì)應(yīng)的位置。
代碼展示:
NSInteger row = self.dataArr.count - 1;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:0];
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
//UITableView 滾動(dòng)到添加的行
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.dataArr.count - 1 inSection:0] atScrollPosition:UITableViewScrollPositionNone animated:YES];
二、UITableView cell的刪除
UITableView 的cell刪除的效果如下:
![Uploading Simulator Screen Shot 2016年10月14日 下午5.55.04_184090.png . . .]](http://upload-images.jianshu.io/upload_images/3238517-72ec984109d01951.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
UITableView 的cell刪除的步驟如下:
1.在UITableView的- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath這個(gè)代理方法中返回YES,來確定UITableView能夠被編輯。
2.在UITableView的- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath這個(gè)代理方法中根據(jù)編輯的類型移除掉相應(yīng)的數(shù)據(jù),然后調(diào)用- (void)deleteRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation或者- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation這個(gè)方法來刪除Cell。
提示:可以在- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath這個(gè)代理方法中設(shè)置刪除按鈕的文字,否則默認(rèn)為delete。
代碼展示:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
return @"刪除";
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.dataArr removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
else if (editingStyle == UITableViewCellEditingStyleInsert)
{
}
else
{
}
}
UITableView的編輯模式
設(shè)置UITableView的editing屬性為YES可以進(jìn)入編輯模式,UITableView的編輯模式有幾種狀態(tài),在UITableView的- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath這個(gè)代理方法中設(shè)置,可以返回一下幾種狀態(tài):
- UITableViewCellEditingStyleNone:cell往右縮進(jìn),但是左邊不出現(xiàn)任何控件
- UITableViewCellEditingStyleDelete:cell往右縮進(jìn),但是左邊出現(xiàn)紅色減號(hào)控件
- UITableViewCellEditingStyleInsert:cell往右縮進(jìn),但是左邊出現(xiàn)藍(lán)色加號(hào)控件
-
UITableViewCellEditingStyleDelete|UITableViewCellEditingStyleInsert:cell往右縮進(jìn),但是左邊出現(xiàn)選擇控件
Simulator Screen Shot 2016年10月16日 下午3.37.04.png
在UITableView的- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath這個(gè)代理方法中對(duì)編輯模式時(shí)的操作(處理選擇操作)進(jìn)行處理,代碼如下:
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
switch (indexPath.row%4) {
case 0:
return UITableViewCellEditingStyleNone;
break;
case 1:
return UITableViewCellEditingStyleDelete;
break;
case 2:
return UITableViewCellEditingStyleInsert;
break;
default:
return UITableViewCellEditingStyleDelete|UITableViewCellEditingStyleInsert;
break;
}
}
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleNone) {
}
else if (editingStyle == UITableViewCellEditingStyleDelete)
{
}
else if (editingStyle == UITableViewCellEditingStyleInsert)
{
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"添加計(jì)劃" message:@"請(qǐng)輸入明日計(jì)劃" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
[alertController addAction:cancelAction];
[self presentViewController:alertController animated:YES completion:nil];
}
else
{
}
}
UITableView cell的選擇
UITableView cell的選擇,我們只需要如下幾步操作即可:
1.進(jìn)入編輯模式(前面已經(jīng)講過)
self.tableView.editing = YES;
2.在UITableView的- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath這個(gè)代理方法中設(shè)置編輯模式為選擇的類型
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
/*
UITableView 編輯狀態(tài)的樣式有如下三種:
UITableViewCellEditingStyleNone:cell往右縮進(jìn),但是左邊不出現(xiàn)任何控件
UITableViewCellEditingStyleDelete:cell往右縮進(jìn),但是左邊出現(xiàn)紅色減號(hào)控件
UITableViewCellEditingStyleInsert:cell往右縮進(jìn),但是左邊出現(xiàn)藍(lán)色加號(hào)控件
UITableViewCellEditingStyleDelete|UITableViewCellEditingStyleInsert:cell往右縮進(jìn),但是左邊出現(xiàn)選擇控件
*/
return UITableViewCellEditingStyleDelete|UITableViewCellEditingStyleInsert;
}
3.在UITableView的- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath和
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath這兩個(gè)代理方法中對(duì)數(shù)據(jù)進(jìn)行操作
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!tableView.editing) {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
else
{
[self.selectedDataArr addObject:self.dataArr[indexPath.row]];
}
}
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView.editing) {
[self.selectedDataArr removeObject:self.dataArr[indexPath.row]];
}
}
4.完成選擇后的操作,這主要根據(jù)需求而定,我在這里做了一個(gè)刪除操作
//插入數(shù)據(jù),刷新界面
NSMutableArray *deleteArr = [NSMutableArray arrayWithCapacity:1];
NSIndexPath *deleteIndexPath = nil;
for (NSString *str in self.selectedDataArr) {
deleteIndexPath = [NSIndexPath indexPathForRow:[self.dataArr indexOfObject:str] inSection:0];
[deleteArr addObject:deleteIndexPath];
}
[self.dataArr removeObjectsInArray:self.selectedDataArr];
[self.selectedDataArr removeAllObjects];
[self.tableView deleteRowsAtIndexPaths:deleteArr withRowAnimation:UITableViewRowAnimationNone];
UITableView cell的移動(dòng)排序
UITableView cell的排序操作其實(shí)和選擇操作非常類似,首先也是進(jìn)入編輯模式,然后在UITableView的- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath的這個(gè)代理方法中返回YES,讓UITableView可以移動(dòng),最后在UITableView的- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath這個(gè)代理方法中對(duì)排序之后的數(shù)據(jù)進(jìn)行操作即可
//設(shè)置tableView編輯狀態(tài)
self.tableView.editing = YES;
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
NSString *exchangeStr = self.dataArr[sourceIndexPath.row];
[self.dataArr removeObjectAtIndex:sourceIndexPath.row];
[self.dataArr insertObject:exchangeStr atIndex:destinationIndexPath.row];
}
UITableView 右滑cell出現(xiàn)多個(gè)按鈕
UITableView 右滑cell出現(xiàn)多個(gè)按鈕在iOS8之前是不支持的,需要自己去實(shí)現(xiàn),在iOS8以后,UITableView的代理中多了這樣一個(gè)方法- (nullable NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath和這樣一個(gè)類UITableViewRowAction,一個(gè)UITableViewRowAction對(duì)象表示一個(gè)按鈕,按鈕的點(diǎn)擊操作包裝在UITableViewRowAction創(chuàng)建方法的block中,在代理方法中返回UITableViewRowAction的數(shù)組就可以了,最先放入數(shù)組的按鈕顯示在最右側(cè),最后放入的顯示在最左側(cè)。
- (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
//添加一個(gè)刪除按鈕
UITableViewRowAction *deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"刪除" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
//處理數(shù)據(jù)
[self.dataArr removeObjectAtIndex:indexPath.row];
//更新UI
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}];
//添加一個(gè)上移按鈕
UITableViewRowAction *upAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:@"上移" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
if (indexPath.row > 0) {
//處理數(shù)據(jù)
[self.dataArr exchangeObjectAtIndex:indexPath.row withObjectAtIndex:indexPath.row - 1];
//更新UI
[tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:indexPath.row - 1 inSection:indexPath.section]] withRowAnimation:UITableViewRowAnimationNone];
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
}];
//添加一個(gè)下移按鈕
UITableViewRowAction *downAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"下移" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
if (indexPath.row < self.dataArr.count - 1) {
[self.dataArr exchangeObjectAtIndex:indexPath.row withObjectAtIndex:indexPath.row + 1];
//更新UI
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
[tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:indexPath.row + 1 inSection:indexPath.section]] withRowAnimation:UITableViewRowAnimationNone];
}
}];
//設(shè)置背景顏色
downAction.backgroundColor = [UIColor colorWithRed:(arc4random()%256)/255.0 green:(arc4random()%256)/255.0 blue:(arc4random()%256)/255.0 alpha:1];
//放回?cái)?shù)組返回
return @[deleteAction, upAction, downAction];
}
需要注意的是:如果我們自己使用UITableViewRowAction設(shè)定了一個(gè)或多個(gè)按鈕,系統(tǒng)自帶的刪除按鈕就失效了。