- 自身遇到问题
- 拓展-进行增删数据时的注意点
- 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方法是什么呢?
- 这两个方法,是配合起来使用的,标记了一个tableView的动画块。
- 分别代表动画的开始和结束。两者成对出现,可以嵌套使用。
- 一般,在
添加
、删除
、选择
tableView中使用,并实现动画效果。 在动画块内,不建议使用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
在如上方法中,建议使用该动画块进行操作!
问答区
- 为什么block属性使用copy修饰?
答:Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的。ARC和非ARC声明都是一样的,当然注意在非ARC下要release Block。
再一次感谢您花费时间阅读这篇文章!
微博: @Danny_吕昌辉
博客: SuperDanny
网友评论