UITableView数据更新问题

  • 自身遇到问题
  • 拓展-进行增删数据时的注意点
    • beginUpdates方法和endUpdates方法是什么呢?
    • 一般什么时候使用这么一个动画块呢?
      • 插入指定的行
      • 插入分组到制定位置
      • 删除制定位置的分组
      • 移动分组
  • 问答区

自身遇到问题

今天在设计自定义UITableViewCell的时候遇到一个愚蠢的问题,就是当用户在Cell上面使用自定义按钮触发删除时,为了保证删除时有动画效果,所以不能在执行deleteRowsAtIndexPaths: withRowAnimation:之后手动执行reloadData
这样就有一个问题,由于不执行reloadData,我们需要获取到Cell最新的indexPath就遇到问题

解决方案:
通过获取按钮所在的Cell的indexPath解决

方式一:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    AMDeleteCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];

    [cell setDeleteBlock:^(NSDictionary *dic, AMDeleteCell *cell) {
  
        //UITableViewCellContentView
        UIView *v = [sender superview];
    
        //UITableViewCell
        UITableViewCell *cell = (UITableViewCell*)[v superview];
        NSIndexPath *indexPath = [tableView indexPathForCell:cell];
        self.deleteIndexPath = indexPath;

    }];

    return cell;

}

方式二(个人认为比较好的一种方式):

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    AMDeleteCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];

    [cell setDeleteBlock:^(NSDictionary *dic, AMDeleteCell *cell) {

        NSIndexPath *indexPath = [tableView indexPathForCell:cell];

        self.deleteIndexPath = indexPath;

    }];

    return cell;

}

自定义Cell内部部分代码:


#import "AMDeleteCell.h"

typedef void(^DeleteCellBlock)(NSDictionary *dic, AMDeleteCell *cell);

@interface AMDeleteCell ()

@property (strong, nonatomic) UIButton        *deleteBtn;
@property (strong, nonatomic) NSDictionary    *dataDic;
@property (copy, nonatomic  ) DeleteCellBlock block;

@end

@implementation AMDeleteCell

//…省略部分代码...

- (void)setDeleteBlock:(void (^)(NSDictionary *, AMDeleteCell *))block {
    self.block = block;
}

#pragma mark - Cell上面按钮触发的方法

- (void)deleteAction:(UIButton *)sender {
    if (_block) {
        _block(_dataDic, self);
    }
}

//...省略部分代码...

@end

拓展-进行增删数据时的注意点

1、普通形式(UITableViewStylePlain)数据增删

将tableView进行增删时需要先更新数据源,然后再执行delete/insert操作

2、分组形式(UITableViewStyleGrouped)数据增删

如果我们的UITableView是UITableViewStyleGrouped的时候,我们如果删除某个Group的最后一条记录时,相应的分组也将被删除。所以,必须保证UITableView的分组,和Cell同时被删除。所以,就需要使用beginUpdates方法和endUpdates方法,将要做的删除操作“包”起来!

beginUpdates方法和endUpdates方法是什么呢?

  1. 这两个方法,是配合起来使用的,标记了一个tableView的动画块。
  2. 分别代表动画的开始和结束。两者成对出现,可以嵌套使用。
  3. 一般,在添加删除选择tableView中使用,并实现动画效果。
  4. 在动画块内,不建议使用reloadData方法,如果使用,会影响动画

一般什么时候使用这么一个动画块呢?

一般在UITableView执行:删除行插入行删除分组插入分组时使用!用来协调UITableView的动画效果。

插入指定的行

在执行该方法时,会对数据源进行访问(分组数据和行数据),并更新可见行。所以,在调用该方法前,应该先更新数据源

- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths
              withRowAnimation:(UITableViewRowAnimation)animation

插入分组到制定位置

插入一个特定的分组。如果,指定的位置上已经存在了分组,那么原来的分组向后移动一个位置。

- (void)insertSections:(NSIndexSet *)sections
      withRowAnimation:(UITableViewRowAnimation)animation

删除制定位置的分组

删除一个制定位置的分组,其后面的分组向前移动一个位置。

- (void)deleteSections:(NSIndexSet *)sections
      withRowAnimation:(UITableViewRowAnimation)animation

移动分组

移动原来的分组从一个位置移动到一个新的位置。如果,新位置上若存在某个分组,那这某个分组将会向上(下)移动到临近一个位置。该方法,没有动画参数。会直接移动。并且一次只能移动一个分组。

- (void)moveSection:(NSInteger)section
          toSection:(NSInteger)newSection

在如上方法中,建议使用该动画块进行操作!


问答区

  1. 为什么block属性使用copy修饰?
    答:Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的。ARC和非ARC声明都是一样的,当然注意在非ARC下要release Block。

再一次感谢您花费时间阅读这篇文章!

微博: @Danny_吕昌辉
博客: SuperDanny

你可能感兴趣的:(UITableView数据更新问题)