###开篇 之前写了几篇商城相关的,规格选择,小控件什么的,今天放一个购物车的代码和实现逻辑,也算对商城系列有个结尾吧。 #####商城系列文章: iOS走近商城APP(一)iOS走近商城APP(二 购物车常用控件) iOS走近商城APP(三 WKWebView 商品规格选择框架封装) iOS走近商城APP(四 runloop应用 获取通讯录并处理) #####本篇文章主要内容 购物车的数据结构的分析 购物车的选中处理逻辑 购物车的数量变化与价格计算 购物车的商品删除与数据刷新 购物车的状态、价格刷新的公共方法
######购物车的数据结构的分析
由图可以看到,所有的数据是包含在一个大的数组内的,大的数组内又包含根据不同的商家区分的不同一级数组,每级数组里对应的是包含各个商品的数据。为了方便做处理,对一个商品数据加入
[dict setObject:@NO forKey:@"checked"];
[dict setObject:@NO forKey:@"checkedSection"];
复制代码
checked表示商品的是否选中的标识,checkedSection标识组是否选中的标识,默认置为NO。构造一个新的数据源来进行操作。
######购物车的选中处理逻辑 首先是cell左侧按钮的选择,同时设置一个临时参数,遍历当前组的时候做自加运算,如果最后数字等于组内数据条数证明全部被选中,设置组选中标识的属性。如果点击的是组上的按钮,遍历数据,把所有的行选中状态置为和组选中相同。同时走价格和选中状态检查的公共方法。全选也是同理,主要的是每次做完操作都要走公共的价格和状态更新方法。
#pragma mark -点击cell上的按钮
-(void)singleClickWithCell:(UITableViewCell *)cell{
NSIndexPath * indexPath = [self.shopCartTableView indexPathForCell:cell];
ShopCartAllDataModel *goodsModel = transformDataArray[indexPath.section][indexPath.row];
goodsModel.checked = !goodsModel.checked;
NSArray *sectionArray = transformDataArray[indexPath.section];//获取当前组内的数组
NSInteger totalCount = 0;
for (int i = 0; i < sectionArray.count; i++) {
ShopCartAllDataModel *goodsModel = transformDataArray[indexPath.section][i];
if (goodsModel.checked) {
totalCount++;
}
}
BOOL sectionSelect = (totalCount == sectionArray.count);
if (sectionSelect) {
ShopCartAllDataModel *model = transformDataArray[indexPath.section][0];
model.checkedSection = YES;
}else{
ShopCartAllDataModel *model = transformDataArray[indexPath.section][0];
model.checkedSection = NO;
};
[self.shopCartTableView reloadData];
[self checkSelcetState];
[self CalculatedPrice];
}
#pragma mark -点击组头试图
-(void)goto_supplier_action:(UIButton *)sectionBtn{
ShopCartAllDataModel *model = transformDataArray[sectionBtn.tag][0];
model.checkedSection =!model.checkedSection;
NSArray *sectionArray = transformDataArray[sectionBtn.tag];
for (int i = 0; i < sectionArray.count; i++) {
ShopCartAllDataModel *goodsModel = transformDataArray[sectionBtn.tag][i];
goodsModel.checked = model.checkedSection;
}
[self.shopCartTableView reloadData];
[self checkSelcetState];
[self CalculatedPrice];
}
#pragma mark -全选按钮
-(void)clickAllSelctBtn{
self.allSelectBtn.selected = !self.allSelectBtn.selected;
if (self.allSelectBtn.selected) {
for (int i= 0; i< transformDataArray.count; i++) {
NSMutableArray *temptArray =[[NSMutableArray alloc]initWithArray:transformDataArray[i]];
for (int j= 0; j <temptArray.count; j++) {
ShopCartAllDataModel *goodsModel = temptArray[j];
goodsModel.checked =YES;
goodsModel.checkedSection =YES;
}
}
[self.shopCartTableView reloadData];
[self CalculatedPrice];
}else{
for (int i= 0; i< transformDataArray.count; i++) {
NSMutableArray *temptArray =[[NSMutableArray alloc]initWithArray:transformDataArray[i]];
for (int j= 0; j <temptArray.count; j++) {
ShopCartAllDataModel *goodsModel = temptArray[j];
goodsModel.checked =NO;
goodsModel.checkedSection =NO;
}
}
[self.shopCartTableView reloadData];
[self CalculatedPrice];
}
}
复制代码
实现的效果如下:
######购物车的数量变化与价格计算 数量的变化控件是单独封装的一个View,加到cell通过cell上的代理处理相关的点击操作,判断当数字小于1的时候不允许继续减少。在每次加减的时候控制中间的数量控件变化的同时要改变model中对应价格的字段的数值,以便能够重新计算价格。
#pragma mark -加减按钮 协议方法
//加
-(void)clickCountViewAddBtnWithCell:(UITableViewCell *)cell WithCountView:(countNumView *)countView{
NSIndexPath * indexPath = [self.shopCartTableView indexPathForCell:cell];
ShopCartAllDataModel *goodsModel = transformDataArray[indexPath.section][indexPath.row];
countView.reduceBtn.enabled =YES;
NSInteger addNum =[countView.countTextfiled.text integerValue];
addNum ++;
countView.countTextfiled.text = [NSString stringWithFormat:@"%ld",addNum];
NSDictionary *rowDic =originalArray[indexPath.section][indexPath.row];
goodsModel.market_price = [NSString stringWithFormat:@"%.2f",[[rowDic objectForKey:@"market_price" ] floatValue]*addNum];
[self.shopCartTableView reloadData];
[self checkSelcetState];
[self CalculatedPrice];
}
//减
-(void)clickCountViewReduceBtnWithCell:(UITableViewCell *)cell WithCountView:(countNumView *)countView{
NSIndexPath * indexPath = [self.shopCartTableView indexPathForCell:cell];
ShopCartAllDataModel *goodsModel = transformDataArray[indexPath.section][indexPath.row];
NSInteger reduceNum =[countView.countTextfiled.text integerValue];
NSDictionary *rowDic =originalArray[indexPath.section][indexPath.row];
if ( reduceNum <= 1) {
countView.reduceBtn.enabled =NO;
goodsModel.market_price = [NSString stringWithFormat:@"%.2f",[[rowDic objectForKey:@"market_price" ] floatValue]*1];
}else{
countView.reduceBtn.enabled =YES;
reduceNum --;
countView.countTextfiled.text = [NSString stringWithFormat:@"%ld",reduceNum];
goodsModel.market_price = [NSString stringWithFormat:@"%.2f",[[rowDic objectForKey:@"market_price" ] floatValue]*reduceNum];
}
[self.shopCartTableView reloadData];
[self checkSelcetState];
[self CalculatedPrice];
}
复制代码
实现效果如下:
######购物车的商品删除与数据刷新 商品的删除首先要存储到想要删除的数据,同时符合选中状态切是右上角按钮状态是编辑状态的信息存储到一个数组内。比如我们存储一个商品的订单号id来作为删选标识。
#pragma mark -结算按钮
-(void)clickMakeSureBtn{
if (self.rightTopBtn.selected) {//删除相关选中商品
for (int i= 0; i< transformDataArray.count; i++) {
NSMutableArray *temptArray =[[NSMutableArray alloc]initWithArray:transformDataArray[i]];
for (int j= 0; j <temptArray.count; j++) {
ShopCartAllDataModel *goodsModel = temptArray[j];
if (goodsModel.checked && self.rightTopBtn.selected) {
//把要删除的数据存进一个数组
[deleteGoodsArray addObject:goodsModel.goods_sn];
[self deletaGoods];//删除数据
}else{
[self deletaGoods];
}
}
}
}else{//结算相关选中商品
for (int i= 0; i< transformDataArray.count; i++) {
NSMutableArray *temptArray =[[NSMutableArray alloc]initWithArray:transformDataArray[i]];
for (int j= 0; j <temptArray.count; j++) {
ShopCartAllDataModel *goodsModel = temptArray[j];
if (goodsModel.checked) {
//得到选中的数据信息
}
}
}
}
}
复制代码
商品信息的删除,这里采用的不是删除二维数组的对应坐标,而是遍历整个数据源,判断如果我们用以保存删除数据的数组deleteGoodsArray内部是否包含当前遍历数据的id,如果不包含,就把他添加到一个新的数据源中,这样,遍历结束,我们得到的一个新的数据源就是所有不包含删除数据的数据源数组,这是用它来替换原来的数据源数据,刷新列表,实现数据的删除。
#pragma mark -处理删除数据 排除要删除信息后新造一个数据源
-(void)deletaGoods{
NSMutableArray *backDetailArray = [[NSMutableArray alloc]init];
for (int i= 0; i< transformDataArray.count; i++) {
NSMutableArray *temptArray =[[NSMutableArray alloc]initWithArray:transformDataArray[i]];
NSMutableArray *sectionDetailArray = [[NSMutableArray alloc]init];
for (int j= 0; j <temptArray.count; j++) {
ShopCartAllDataModel *goodsModel = temptArray[j];
if (![deleteGoodsArray containsObject:goodsModel.goods_sn]) {
[sectionDetailArray addObject:transformDataArray[i][j]];
}
}
if (sectionDetailArray.count) {
[backDetailArray addObject:sectionDetailArray];
}
}
[transformDataArray removeAllObjects];
[transformDataArray addObjectsFromArray:backDetailArray];
[self.shopCartTableView reloadData];
[self CalculatedPrice];
}
复制代码
实现效果如下:
######购物车的状态、价格刷新的公共方法 公共方法主要是两个,用以遍历选中状态和每次操作后的价格数据刷新。
#pragma mark -每次选中都走的方法检查是否全部选中
-(void)checkSelcetState{
NSInteger totalSelected = 0;
NSInteger realRowNum = 0;
for (int i= 0; i< transformDataArray.count; i++) {
NSMutableArray *temptArray =[[NSMutableArray alloc]initWithArray:transformDataArray[i]];
for (int j= 0; j <temptArray.count; j++) {
ShopCartAllDataModel *goodsModel = temptArray[j];
realRowNum ++;
if (goodsModel.checked) {
totalSelected ++;
}
}
}
if (totalSelected == realRowNum) {
self.allSelectBtn.selected =YES;
}else{
self.allSelectBtn.selected =NO;
}
}
#pragma mark - 价格的计算
-(void)CalculatedPrice{
float price = 0;
for (int i= 0; i< transformDataArray.count; i++) {
NSMutableArray *temptArray =[[NSMutableArray alloc]initWithArray:transformDataArray[i]];
for (int j= 0; j <temptArray.count; j++) {
ShopCartAllDataModel *goodsModel = temptArray[j];
if (goodsModel.checked) {
price = price+ [goodsModel.market_price floatValue];
}
}
}
self.priceLabel.text = [NSString stringWithFormat:@"%.2f元",price];
}
复制代码
核心基本就是这些了,这样我们就简单实现了一个简单的小购物车的逻辑。至于一些加入购物车的过期商品,下架商品的处理逻辑,以后有机会了再慢慢更新到git上吧。只是为了实现一个简单的功能,有些地方可能写的不够简洁和规范,主要是希望总结下思路练练手。有不好的地方多包涵,下面里面放上git地址,千万别说故意不放代码,哈哈