- 写在前边吧,自己太菜了,花了前前后后差不多一天多时间才完全弄清楚
(掉坑了~)
,这玩意儿必须记录一下(篇幅不是很大,逻辑较绕,建议静得下来再食用)
需求:
需求
如图所示(后悔自己当时没画图,走入误区!吸取教训了....)
,cell中的button
对应了这几种情况,底部选择View
有全选、清空、标记已读
三种逻辑。
一、思考
- 首先,别去想什么
禁止tableView复用
,这个想法很low,而且很危险、直接不成立,跳过! - 其次、参考网上很多的
点赞
效果实现,修改对应model数据,刷新UI即可,逻辑上是这样的,成立。 - 确定好方向后,开始动工分析,cell中,确定自己按钮能够达到效果,需要建立的模型数据情况
(这句话可能有点绕,接下来我举例说明)
二、思路讲解
tip1:点赞逻辑(较简单)
- 1、假如,你就是实现点赞逻辑,那么只需要在模型里建立一个按钮是否选中的BOOL就OK了。
/** 按钮是否选中状态*/
@property (nonatomic,assign)BOOL selected;
- 2、在cell中,模型赋值的方法里,让对应的按钮的选中状态 = model.selected 。
self.selectedBtn.selected = model.selected;
- 3、在VC中,利用cell的按钮
block
、或者自定义协议
里,取得cell对应在tableView数据源 中的 model数据,通过block、协议传递过来的按钮是否选中的selected BOOL值来改变model里的selected
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
EHSMessageModel *model = self.dataList[indexPath.row];
model.selected = selected;
- 4、刷新UI,发送点赞(取消点赞)的请求
tip2:多选、全选进行删除、购物车结算、标记已读等逻辑(较复杂)
-
网上也有很多教程,但大多数都是使其处于
编辑状态
,这并不符合我的需求(如果你的业务需求也是处于 编辑状态 的情况,你可以选择不用继续看接下来的内容,直接跳过我去做自己的逻辑)
。 -
1、依旧是建立模型数据--BOOL
@property (nonatomic,assign)BOOL selected;
- 2、在cell中,使按钮选中状态 对应模型数据
self.selectedBtn.selected = model.selected;
-
3、在VC中,初始化
删除数据的Arr
,结算数据的Arr
,已读数据的Arr
等,用来在全选、多选、单选后,装载对应操作的数据。 -
4、在VC中,利用cell的按钮
block
、或者自定义协议
里,取得cell对应在tableView数据源 中的 model数据,通过block、协议传递过来的按钮是否选中的selected BOOL值,来改变model里的selected。(主要是对要操作的数据做相应更改)
cell.selectBtnClick = ^(BOOL isSelected) {
//1、取得对应模型
BuyCarModel *model = _weakSelf.carListArr[indexPath.row];
//2、改变模型BOOL值
model.isSelected = isSelected;
//3、按钮选中状态对应的操作
if (isSelected) {
//这里是以购物车结算为例子
global_jiesuanNum += [model.num intValue];
global_totalPrice += [model.num intValue] * [model.shop_price floatValue];
_weakSelf.totalPriceLbl.text = [NSString stringWithFormat:@"¥%.2f", global_totalPrice];
[_weakSelf.jiesuanBtn setTitle:[NSString stringWithFormat:@"结算(%d)", global_jiesuanNum] forState:UIControlStateNormal];
//这里是将修改后的模型数据添加到对应操作的数组中
[_weakSelf.jiesuanArr addObject:model];
[_weakSelf.collectOrDeleteArr addObject:model.car_id];
} else {//3.1、按钮对应取消选中的操作
//取消结算的操作
global_jiesuanNum -= [model.num intValue];
global_totalPrice -= [model.num intValue] * [model.shop_price floatValue];
_weakSelf.totalPriceLbl.text = [NSString stringWithFormat:@"¥%.2f", global_totalPrice];
[_weakSelf.jiesuanBtn setTitle:[NSString stringWithFormat:@"结算(%d)", global_jiesuanNum] forState:UIControlStateNormal];
//同样的,对应移除模型数据
[_weakSelf.jiesuanArr removeObject:model];
[_weakSelf.collectOrDeleteArr removeObject:model.car_id];
}
// 判断 如果有一个cell未被选中,全选按钮取消被选中
for (BuyCarModel *model in self.carListArr) {
if (!model.isSelected) {
_bottomSelectBtn.selected = NO;
}
}
// 判断 如果所有的cell被选中,全选按钮也被选中
int selectCount = 0;
for (BuyCarModel *model in self.carListArr) {
if (model.isSelected) {
selectCount ++;
}
}
if (selectCount == self.carListArr.count) {
_bottomSelectBtn.selected = YES;
}
};
- 5、对应全选、删除、标记已读、结算等 按钮的响应事件
(tag推荐用枚举,这里例子主要表明对应逻辑和操作过程)
- (IBAction)bottomBtnClick:(UIButton *)button {
if (button.tag == 1) { // 全选事件
button.selected = !button.selected;
if (button.selected) {
self.bottomSelectBtn.selected = YES;
int i = 0;
float totalCount = 0;
for (BuyCarModel *model in self.carListArr) {
model.isSelected = YES;
float total = [model.num intValue] * [model.shop_price floatValue];
totalCount += total;
i += [model.num intValue];
[self.jiesuanArr addObject:model];
[self.collectOrDeleteArr addObject:model.car_id];
}
global_jiesuanNum = I;
global_totalPrice = totalCount;
[_jiesuanBtn setTitle:[NSString stringWithFormat:@"结算(%d)", i] forState:UIControlStateNormal];
_totalPriceLbl.text = [NSString stringWithFormat:@"¥%.2f", totalCount];
// 刷新表格
[self.tableView reloadData];
} else {
self.bottomSelectBtn.selected = NO;
for (BuyCarModel *model in self.carListArr) {
model.isSelected = NO;
[self.jiesuanArr removeObject:model];
[self.collectOrDeleteArr removeObject:model.cat_id];
}
[_jiesuanBtn setTitle:@"结算(0)" forState:UIControlStateNormal];
_totalPriceLbl.text = @"¥0";
global_jiesuanNum = 0;
global_totalPrice = 0;
// 刷新表格
[self.tableView reloadData];
}
} else if (button.tag == 2) { //结算事件
if (![_jiesuanBtn.titleLabel.text isEqualToString:@"结算(0)"]) {
ConfirmOrderViewController *confirmOrderVC = [[ConfirmOrderViewController alloc] init];
confirmOrderVC.buyStatus = @"1";
confirmOrderVC.buyCarArr = self.jiesuanArr;
[self.navigationController pushViewController:confirmOrderVC animated:YES];
}
} else if (button.tag == 3) { //删除事件
if (self.collectOrDeleteArr.count == 0) {
[SVProgressHUD showErrorWithStatus:@"请选择删除数据"];
} else {
// 删除选中的物品
[JXTAlertTools showAlertWith:self title:@"确定删除当前选定的商品?" message:nil callbackBlock:^(NSInteger btnIndex) {
if (btnIndex == 1) {
// [self getCarDelData];
}
} cancelButtonTitle:@"取消" destructiveButtonTitle:@"确定" otherButtonTitles:nil, nil];
}
}else if (button.tag == 4) { // 添加收藏
if (self.collectOrDeleteArr.count == 0) {
[SVProgressHUD showErrorWithStatus:@"未选择删除数据"];
}
}
}
三、讲讲自己是怎么掉坑的(可不看)
因为,我的需求里,已读信息和未读信息,均可被选中,未读信息选中后,变为已读,问题来了,已读信息,选中后呢?变成什么?也是已读吗?
我先假使已读信息 选中后模型数据由原先的@"1"
变为@"2"
,未读模型数据由原先的@"0"
变为@"1"
,再取消选中的时候再对应还原。。。。
表面上没什么问题,可实际上,当我先选择第一行未读,那么 第一行原本的@"0"
变为@"1"
,但是我再全选,那么 第一行原本的@"1"
变为@"2"
,其他的cell原本的@"0"
变为@"1"
、@"1"
变为@"2"
,也就是说,现在我还原不了第一行到@"0"
,只能把它变为@"1"
,这样就出现bug了,根本就还原不了这种情况下的未读信息。
四、怎么达到最终需求的(爬坑)
- 很简单,因为,我本身不只一个 选中与不选中的情况
(这种情况按照上面的介绍,完全可以解决)
,而是分 已读选中未选中、未读选中未选中的情况,所以一条模型数据是否选中,已经无法满足,增加一条 原始cell是否已读的模型数据,判断的时候,对应的在逻辑里,加入是否原始已读。就行了...行了...了...(可怜我郁闷了很久...)
/** 按钮是否选中状态*/
@property (nonatomic,assign)BOOL selected;
/** 是否选原来就是已读 状态*/
@property (nonatomic,assign)BOOL isOriginalRead;
- 结语:我是参照的华之曦写的这篇文章,感谢开源精神,没上传Demo,如有什么疑问,可评论留言或者私信。期待成长...
网友评论