UITableView的代理方法,实现编辑、删除、排序、多选

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/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容