UITableView 编辑总结

作者: 酒茶白开水 | 来源:发表于2016-10-17 00:20 被阅读1397次

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

    一、总述

    在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 . . .]](https://img.haomeiwen.com/i3238517/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设定了一个或多个按钮,系统自带的删除按钮就失效了。

    相关文章

      网友评论

        本文标题:UITableView 编辑总结

        本文链接:https://www.haomeiwen.com/subject/uyfnyttx.html