iOS走近商城APP(五 购物车)

开篇

之前写了几篇商城相关的,规格选择,小控件什么的,今天放一个购物车的代码和实现逻辑,也算对商城系列有个结尾吧。

商城系列文章:

iOS走近商城APP(一)
iOS走近商城APP(二 购物车常用控件)
iOS走近商城APP(三 WKWebView 商品规格选择框架封装)
iOS走近商城APP(四 runloop应用 获取通讯录并处理)

本篇文章主要内容

购物车的数据结构的分析
购物车的选中处理逻辑
购物车的数量变化与价格计算
购物车的商品删除与数据刷新
购物车的状态、价格刷新的公共方法


效果图.png
购物车的数据结构的分析
数据结构.png

由图可以看到,所有的数据是包含在一个大的数组内的,大的数组内又包含根据不同的商家区分的不同一级数组,每级数组里对应的是包含各个商品的数据。为了方便做处理,对一个商品数据加入

        [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];
        
    }
}

实现的效果如下:


选中.gif
购物车的数量变化与价格计算

数量的变化控件是单独封装的一个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];
    
}

实现效果如下:


价格变化.gif
购物车的商品删除与数据刷新

商品的删除首先要存储到想要删除的数据,同时符合选中状态切是右上角按钮状态是编辑状态的信息存储到一个数组内。比如我们存储一个商品的订单号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];
}

实现效果如下:


删除.gif
购物车的状态、价格刷新的公共方法

公共方法主要是两个,用以遍历选中状态和每次操作后的价格数据刷新。

#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地址,千万别说故意不放代码,哈哈


否认三连.jpg

git地址,喜欢的star一下😜

代码在这里,看这里:
购物车项目代码ShopCartTest

后记

搞了一年多的商城,也写了几篇多多少少和项目有关的文章,最后还是补上了购物车,毕竟没有购物车的商城不叫真正的商城,哈哈。接下来估计要转入新项目,看看有没有机会写一个别的系列吧,这些文章算是自己的一个小小的总结吧,也希望对有需要的同学有所帮助。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,074评论 25 707
  • 导语 使用RAC实践购物车逻辑的梳理!首先分析ViewModel里面的每一个属性,然后分析ViewModel里面的...
    Carden阅读 630评论 0 0
  • 心血来潮,突然想把自己这几年的经历与感想记录于《简书》。原因如下: 一、记录自己的生活...
    一个口吃患者阅读 153评论 0 0
  • 随着人们生活水平的不断提高,生活节奏的加快,人们可分配的时间越来越碎片化,而阅读、咨询类的APP则可以很好...
    Mis葳阅读 724评论 0 2
  • 根据我们的统计分析,目前使用的人最多的教材是北京大学的《标准韩国语》,大的培训机构倾向于使用韩国原版的教材,如《新...
    韩语皎皎老师阅读 720评论 0 0