美文网首页selector进阶iOS Developer
两个代理方法实现iOS购物车1-精简版

两个代理方法实现iOS购物车1-精简版

作者: 马铃薯蜀黍 | 来源:发表于2017-02-22 15:47 被阅读558次
    首页图.png

    没有用到通知.只要两个代理方法实现购物车

    github的地址:https://github.com/zhYes/YSShoppingCar.git

    效果展示:

    购物车.gif

    二. 简介:

    1.第三方:用到的框架SDWebImage/MJExtension,应该都很熟悉,第一个是图片下载,第二个是字典转模型.

    2.功能: ①勾选总价计算; ②删除功能

    三. 使用:

    0.拖入相关文件

    #import "ViewController.h"
    #import "MKShopCarController.h"
    #import "MKOrderListModel.h"
    #import "MJExtension.h"
    

    1.传递数据

    // 传递模型数据
    - (void)shopCarClick {
        MKShopCarController * shop = [MKShopCarController new];
        shop.modelList = _nmArray;
        [self.navigationController pushViewController:shop animated:YES];
    }
    

    2.修改模型数据


    修改模型key值.png

    @end
    @end

    四. 代码实现

    • 1
    // 继承UIViewController
    @interface MKShopCarController   : UIViewController
    
    // 设置表格
    - (void)setTableList {
        _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
        [self.view addSubview:_tableView];
        _tableView.delegate = self;
        _tableView.dataSource = self;
        UINib * nib = [UINib nibWithNibName:@"MKShopCarCell" bundle:nil];
        [_tableView registerNib:nib forCellReuseIdentifier:@"shop"];
        _tableView.rowHeight = 110;
        _tableView.contentInset = UIEdgeInsetsMake(0, 0, 49, 0);
    }
    

    这里创建为UITableViewStylePlain样式组头会停住
    UITableViewStyleGroup样式组头不会停住,这也是分组样式与否的区别

    • 2.第一个代理方法,自定义cell中,选中按钮的点击事件
      并且将当前的cell的tag值传递回控制器中
    //自定义cell中
    @interface MKShopCarCell : UITableViewCell
    
    // 自定义cell中左侧选中按钮的点击事件
    - (IBAction)fabricSelectClick:(UIButton*)sender {
        _goodsModel.isSelected = !_goodsModel.isSelected;
        fabricSelectedBtn.selected = !fabricSelectedBtn.selected;
    //    NSLog(@"%zd",self.tag);
        if ([self.shopDelegate respondsToSelector:@selector(shopCellSelectedClick:)]) {
            [self.shopDelegate shopCellSelectedClick:self.tag];
        }
    }
    
    • 3.第二个代理方法,自定义组头中,选中按钮的点击事件中
      同样将当前section中tag传递
    //自定义组头中
    @interface MKHeaderFooterView : UITableViewHeaderFooterView
    
    // 组头的点击事件
    - (void)headerBtnClick: (UIButton*)HeaderBtn :(NSInteger)section{
        HeaderBtn.selected = !HeaderBtn.selected;
        if ([self.headerDelegate respondsToSelector:@selector(headerSelectedBtnClick:)]) {
            [self.headerDelegate headerSelectedBtnClick:self.tag];
        }
    }
    
    • 4.控制器中,遵守协议,实现这两个代理方法
    <UITableViewDelegate,UITableViewDataSource,shopCarCellDelegate,headerViewDelegate>
    
    // 注册cell/header 或者判断为空的时候 创建
        UINib * nib = [UINib nibWithNibName:@"MKShopCarCell" bundle:nil];
        [_tableView registerNib:nib forCellReuseIdentifier:@"shop"];
    
      • 组头的数据方法 | 绑定tag
    - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
        
        _headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"MKShopCarHeader"];
        
        if (_headerView == nil) {
            
            _headerView = [[MKHeaderFooterView alloc] init];
            _headerView.headerDelegate = self;
        }
        
        MKOrderListModel*listModel = _modelList[section];
        
        _headerView.tag = section;
        _headerView.headerBtn.selected = listModel.groupSelected;
        
        return _headerView;
    }
    
    
    •   -     cell的数据源方法 | 绑定tag
      
    // cell显示内容
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
         MKShopCarCell*shopCell = [tableView dequeueReusableCellWithIdentifier:@"shop"];
        shopCell.shopDelegate = self;
        //取出对应组的对应商品信息
        shopCell.goodsModel = ((MKOrderListModel*)_modelList[indexPath.section]).goods[indexPath.row];
        
        // 给cell做标记
        shopCell.tag = (long)indexPath.section *100 + (long)indexPath.row;
    //    if (_modelList.count != self.dic.count) {
        
            NSString * cellTag = [NSString stringWithFormat:@"%zd",shopCell.tag];
            NSDictionary* _tempDic = @{
                         cellTag:indexPath
                         };
            [self.dic addEntriesFromDictionary:_tempDic];
    //    }
        return shopCell;
    }
    

    这里将所有的indexpath存入一个字典里,并通过对应的tag作为key值
    为保证唯一性section和row都做了处理作为key

      • 实现cell中的代理方法 | 计算选中与未选中的总价
    #pragma mark - cell上的代理方法获 | 取的价格
    - (void)shopCellSelectedClick:(NSInteger)shopCellTag {
        
        //判断组的是否选中状态是否修改
        NSString * cellTagStr = [NSString stringWithFormat:@"%zd",shopCellTag];
        NSIndexPath *indexPath = self.dic[cellTagStr];
        MKOrderListModel * listModel = (MKOrderListModel*)_modelList[indexPath.section];
        
        //0.便利当前组cell上选中按钮的个数
        NSInteger seletedNum =0;
        for (MKGoodsModel* goodsModel in listModel.goods) {
            if (goodsModel.isSelected) {
                seletedNum += 1;
            }
            
            // 1.当前组的cell的个数 是否等于 勾选的总数
            if (((MKOrderListModel*)_modelList[indexPath.section]).goods.count == seletedNum) {
                listModel.groupSelected = YES;
            } else {
                listModel.groupSelected = NO;
            }
            [_tableView reloadData];
        }
        
        MKGoodsModel *goodsModel = ((MKOrderListModel*)_modelList[indexPath.section]).goods[indexPath.row];
        float shop_price = goodsModel.shop_price;
        float goods_number = goodsModel.goods_number;
        if (!goodsModel.isSelected) {
            _totalNum = _totalNum - shop_price*goods_number;
        }else {
            
            _totalNum = _totalNum + shop_price*goods_number;
        }
        _hejiLabel.text = [NSString stringWithFormat:@"¥%.2f",_totalNum -1 + 1];
    }
    
    

    即,根据代理中的tag 取出 indexpath 再根据indexpath 取出模型中的数据
    另外判断本组中的cell都选中时候组的选中状态也为选中!

      • 实现header中我们写的的代理方法 | 计算选中与未选中的总价
    #pragma mark - 代理方法组头header的选中状态
    - (void)headerSelectedBtnClick:(NSInteger)section {
        //    NSLog(@"%zd",section);
        MKOrderListModel*listModel = _modelList[section];
        listModel.groupSelected = !listModel.groupSelected;
        
        // 判断如果点击 | header选中
        if (listModel.groupSelected) {
            
            for (MKGoodsModel* goodsModel in listModel.goods) {
                
                if (!goodsModel.isSelected) {                      //下面不是选中状态的cell 将价格加入到总价当中
                    float shop_price = goodsModel.shop_price;     //价格
                    float goods_number = goodsModel.goods_number;   // 数量
                    _totalNum += shop_price * goods_number;
                    goodsModel.isSelected = YES;
                }
                
            }
        } else {  // 取消header选中 所有都取消
            for (MKGoodsModel* goodsModel in listModel.goods) {
                goodsModel.isSelected = NO;
                float shop_price = goodsModel.shop_price;               //价格
                float goods_number = goodsModel.goods_number;   // 数量
                _totalNum -= shop_price * goods_number;
            }
        }
    //    NSLog(@"总价格为: %.2f",_totalNum);
        _hejiLabel.text = [NSString stringWithFormat:@"¥%.2f",_totalNum - 1 + 1];
        [_tableView reloadData];
    }
    
    

    逻辑分析: 组头点击选中 : 则遍历本组cell 未选中状态的cell计算价格加入到总价更并改cell选中状态
    组头点击未选中 : 遍历本组中cell 的价格 从总价中减去并更改cell的选中状态
    最后reloadData

      • 删除方法 | 根据方法中自带的indexpath从数据中删除跟新即可
    //左拉抽屉(删除和修改按钮)
    - (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        // 添加一个删除按钮
        UITableViewRowAction *deleteRowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:@"删除"handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
            
            MKOrderListModel*listModel = _modelList[indexPath.section];
            
            NSMutableArray*goodsModel = (NSMutableArray*)listModel.goods;
            
            /// 如果删除的是带勾选的则计算一次数值
            MKGoodsModel*goodModel = (MKGoodsModel*)goodsModel[indexPath.row];
            if (goodModel.isSelected) {
                float shop_price = goodModel.shop_price;               //价格
                float goods_number = goodModel.goods_number;   // 数量
                _totalNum -= shop_price * goods_number;
                _hejiLabel.text = [NSString stringWithFormat:@"%.2f",_totalNum];
            }
            
            [goodsModel  removeObjectAtIndex:indexPath.row];    // 删除操作放到最后
            
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
            if (goodsModel.count == 0) {
                NSMutableArray *temp = [NSMutableArray arrayWithArray:_modelList];
                [temp removeObjectAtIndex:indexPath.section];
                _modelList = temp;
            }
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                
                [tableView reloadData];
            });
        }];
        
        // 修改资料按钮
        UITableViewRowAction *editRowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"修改"handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
            
        }];
        
        editRowAction.backgroundColor = [UIColor blueColor];
        // 将设置好的按钮放到数组中返回
        return @[deleteRowAction, editRowAction];
    }
    
    

    注意点 : ①可能遇到删除报错的情况,需要条件到一个临时的可变数组中做删除操作 再把删除后的数组回传
    ②判断删除cell中的选中,如果选中状态则在总价中减去此价格即可
    ③删除操作这里需要增加接口后台数据做删除

    纯手打,如果有用希望多多支持!~

    两个代理方法实现iOS购物车2-完整版

    相关文章

      网友评论

      • 坏小孩泡泡糖:你这个bug还不少呢 哈哈哈 我下下来了
        马铃薯蜀黍:@坏小孩泡泡糖 组头数据放在数组里拿的随机数据,所以每次刷新都随机取了
        坏小孩泡泡糖:@马铃薯蜀黍 你没发现 点击一个标题的时候 ,标题头的文字会变吗?还有那个价格 不是很准确,这个倒不是啥大问题,只是数据的事,在toolbar有个 全选 不挺好吗?
        马铃薯蜀黍:@坏小孩泡泡糖 说说看
      • 坏小孩泡泡糖:这个不能 编辑吗?就是 选择购买的数量 点击加减号的?
        马铃薯蜀黍:@坏小孩泡泡糖 没有,因为我们业务需求是跳详情修改,加减能做问题不大
      • a24df6838a47:这个好
        马铃薯蜀黍:http://www.jianshu.com/p/36096fcaaf7c完整版购物车
        马铃薯蜀黍:@王晓鹏友 感谢喜欢还是有很多不足

      本文标题:两个代理方法实现iOS购物车1-精简版

      本文链接:https://www.haomeiwen.com/subject/neipwttx.html