UITableView 编辑总结

代码下载地址一
代码下载地址二

一、总述

在iOS开发中,UITableView的使用率可以说是非常高的,所以它在iOS开发中的地位是无法替代的。最近项目涉及到UITableView的编辑问题,这个问题其实非常广泛,我希望从我的角度尽可能地把这个问题思虑全面,讲述清楚。

UITableView的编辑,我主要从这些方面来讲述:cell的插入,删除,选择,移动排序以及UITableView的编辑模式等。

二、UITableView cell的插入

UITableView cell的插入首先要保证UITableView的数据源插入了数据,否则会发生奔溃。正确地插入了数据之后,可以通过一下几种方式达到插入Cell的效果:

1.刷新UITableView,既调用UITableView的-reloadData:方法或者-reloadSections: withRowAnimation:方法,其实还有其他的一些刷新UITableView的方式。但是我要说的是使用这种方式的话性能方面不是很好,因为刷新UITableView会调用很多次代理方法。

2.直接插入Cell,既调用UITableView的insertRowsAtIndexPaths:withRowAnimation:方法或者insertSections: withRowAnimation:方法来插入。这种方式相对性能较高。

需要注意的问题:插入了Cell最好还是调用一下UITableView的-scrollToRowAtIndexPath:atScrollPosition:UITableViewScrollPositionNoneanimated:这个方法,把UITableView滚动到对应的位置。

代码展示:

NSInteger row = self.dataArr.count - 1;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:0];
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
        
 //UITableView 滚动到添加的行
[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)

Simulator Screen Shot 2016年10月14日 下午5.55.04.png

Simulator Screen Shot 2016年10月14日 下午5.55.05.png

UITableView 的cell删除的步骤如下:
1.在UITableView的- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath这个代理方法中返回YES,来确定UITableView能够被编辑。
2.在UITableView的- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath这个代理方法中根据编辑的类型移除掉相应的数据,然后调用- (void)deleteRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation或者- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation这个方法来删除Cell。
提示:可以在- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath这个代理方法中设置删除按钮的文字,否则默认为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的编辑模式

设置UITableView的editing属性为YES可以进入编辑模式,UITableView的编辑模式有几种状态,在UITableView的- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath这个代理方法中设置,可以返回一下几种状态:

  • UITableViewCellEditingStyleNone:cell往右缩进,但是左边不出现任何控件
  • UITableViewCellEditingStyleDelete:cell往右缩进,但是左边出现红色减号控件
  • UITableViewCellEditingStyleInsert:cell往右缩进,但是左边出现蓝色加号控件
  • UITableViewCellEditingStyleDelete|UITableViewCellEditingStyleInsert:cell往右缩进,但是左边出现选择控件


    Simulator Screen Shot 2016年10月16日 下午3.37.04.png

    在UITableView的- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath这个代理方法中对编辑模式时的操作(处理选择操作)进行处理,代码如下:

-(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:@"添加计划" message:@"请输入明日计划" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
        [alertController addAction:cancelAction];
        [self presentViewController:alertController animated:YES completion:nil];
    }
    else
    {
        
    }
}

UITableView cell的选择

Simulator Screen Shot 2016年10月16日 下午5.52.58.png
Simulator Screen Shot 2016年10月16日 下午5.53.00.png

UITableView cell的选择,我们只需要如下几步操作即可:
1.进入编辑模式(前面已经讲过)
self.tableView.editing = YES;
2.在UITableView的- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath这个代理方法中设置编辑模式为选择的类型

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
    /*
     UITableView 编辑状态的样式有如下三种:
        UITableViewCellEditingStyleNone:cell往右缩进,但是左边不出现任何控件
        UITableViewCellEditingStyleDelete:cell往右缩进,但是左边出现红色减号控件
        UITableViewCellEditingStyleInsert:cell往右缩进,但是左边出现蓝色加号控件
        UITableViewCellEditingStyleDelete|UITableViewCellEditingStyleInsert:cell往右缩进,但是左边出现选择控件
     */
        return UITableViewCellEditingStyleDelete|UITableViewCellEditingStyleInsert;
  }

3.在UITableView的- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath和

  • (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath这两个代理方法中对数据进行操作
-(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.完成选择后的操作,这主要根据需求而定,我在这里做了一个删除操作

            //插入数据,刷新界面
            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的移动排序

Simulator Screen Shot 2016年10月16日 下午5.55.06.png
Simulator Screen Shot 2016年10月16日 下午5.55.22.png

UITableView cell的排序操作其实和选择操作非常类似,首先也是进入编辑模式,然后在UITableView的- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath的这个代理方法中返回YES,让UITableView可以移动,最后在UITableView的- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath这个代理方法中对排序之后的数据进行操作即可

//设置tableView编辑状态
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出现多个按钮

Simulator Screen Shot 2016年10月16日 下午11.46.10.png

UITableView 右滑cell出现多个按钮在iOS8之前是不支持的,需要自己去实现,在iOS8以后,UITableView的代理中多了这样一个方法- (nullable NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath和这样一个类UITableViewRowAction,一个UITableViewRowAction对象表示一个按钮,按钮的点击操作包装在UITableViewRowAction创建方法的block中,在代理方法中返回UITableViewRowAction的数组就可以了,最先放入数组的按钮显示在最右侧,最后放入的显示在最左侧。

- (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //添加一个删除按钮
    UITableViewRowAction *deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"删除" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
        //处理数据
        [self.dataArr removeObjectAtIndex:indexPath.row];
        //更新UI
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
    }];
    
    //添加一个上移按钮
    UITableViewRowAction *upAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:@"上移" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
        if (indexPath.row > 0) {
            //处理数据
            [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];
        }
    }];
    
    //添加一个下移按钮
    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];
        }
    }];
    
    //设置背景颜色
    downAction.backgroundColor = [UIColor colorWithRed:(arc4random()%256)/255.0 green:(arc4random()%256)/255.0 blue:(arc4random()%256)/255.0 alpha:1];
    
    //放回数组返回
    return @[deleteAction, upAction, downAction];
}

需要注意的是:如果我们自己使用UITableViewRowAction设定了一个或多个按钮,系统自带的删除按钮就失效了。

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

推荐阅读更多精彩内容