支付详解demo

iOS Demo 详解(二) 购物车

2017-03-01  本文已影响102人  5a9c6f44e578

demo下载地址:
https://git.oschina.net/wwwzz/ShoppingCartDemo

可以照着model看,思路清楚一点

先看效果图


Paste_Image.png

先来分析下,要实现的功能:
1.页面内容展现
这里因为找不到合适数据,文字内容是从网易新闻获取的,图片是本地的,在加一些按钮.之所以获取网易的文字展现是为了练习解决下滑动内容混乱的问题

2.加,减,选中按钮, 功能实现

3.总价格展示

4.全选按钮实现,没有选中的加1选中的不变,再次点击全部不选

5.选中收藏,把数据存到本地数据库
这里强调一下,购物车数据还是应该存到后台,因为要考虑切换设备的情况,这里存到本地仅仅是为了练习数据库存图片

6.其他功能

第一个比较简单就不讲解了,具体看demo吧

第二个功能:

先在 cell 设置代理

Paste_Image.png

.m 传递 tag 用以区分是哪个cell 上的控件

Paste_Image.png Paste_Image.png

看代理实现前先写model

Paste_Image.png

.m 图片是本地的所以给了固定值,价格是为了好算

Paste_Image.png

</br>
控制器的宏定义 属性 和代理


Paste_Image.png

</br>

数据源中设置代理,并把indexPath.row 当做tag值传递,区分cell,根据model中的BOOL值判断选择状态, 使用KVC修改占位符颜色

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
    LXTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"111"];
    
    if(cell == nil){
        cell = [[LXTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"111"];
    }
    cell.delegate = self;
    
    [cell.numberTF addTarget:self action:@selector(textFieldDidChange:) forControlEvents:(UIControlEventEditingChanged)];
    
    // cell 上 传递  tag
    cell.selectBtn.tag = indexPath.row;

    cell.rightButton.tag = indexPath.row;

    cell.leftButton.tag = indexPath.row;
    
    LXModel *model = self.MyArray[indexPath.row];
    
// 获取 网易新闻字符串
    [cell setCellModel:model];
    
    cell.selectBtn.selected = model.isBtnSelect;
    
    cell.PictureImage.image = [UIImage imageWithData:model.picture];
    
    if (cell.selectBtn.selected == YES){
        
        [cell.selectBtn setImage:[UIImage imageNamed:@"选中"] forState:(UIControlStateNormal)];
    }else if(cell.selectBtn.selected == NO){
        [cell.selectBtn setImage:[UIImage imageNamed:@"未选中"] forState:(UIControlStateNormal)];
    }
    
    if (model.number == nil || model.number <= 0) {
        cell.numberTF.text = @"";
        cell.numberTF.placeholder = @"0";
    }else if(model.number != nil){
        cell.numberTF.text = model.number;
    }
    
// 价格
    cell.priceLabel.text = [NSString stringWithFormat:@"%ld",model.DanGeJiaGe];
    
    cell.numberTF.delegate = self;
    
    // 使用KVC 修改占位符  颜色
    [cell.numberTF setValue:[UIColor whiteColor] forKeyPath:@"_placeholderLabel.textColor"];
    return  cell;
}

</br>
</br>
cell 选中代理方法
self.MyArray 里面装的是请求下来的网易新闻字符串
两个model是用来互相替换的,这样可以解决滑动时数据不对称

//  选中  代理
- (void)selectAtIndex:(NSInteger)row{
    
    LXModel *model =  self.MyArray[row];
    
    LXModel *tempModel = [[LXModel alloc]init];

    tempModel.alias = model.alias;
    
    tempModel.picture = model.picture;
    
    if (model.isBtnSelect == YES){
        
        NSInteger  tempNumber = [tempModel.number integerValue];

//  取消选中状态  直接清0
        if (tempNumber == 0){
            tempModel.number = @"";
        }

        tempModel.isBtnSelect = NO;
        
    } else if (model.isBtnSelect == NO){
        
        tempModel.isBtnSelect = YES;
  
        NSInteger  tempNumber = [tempModel.number integerValue];

//  选中加一
        tempNumber++;

        tempModel.number = [NSString stringWithFormat:@"%ld",tempNumber];
    }

    //替换
    [self.MyArray replaceObjectAtIndex:row withObject:tempModel];
    
// 计算总和
    _zongHeLabel.text = [self ZongHeJiSuan:self.MyArray];
    
    [self.mainTableView reloadData];
}

</br>
加减 一样 减号注意别小于0

//   添加的  btn  代理
- (void)addButtonDelegate:(NSInteger)row{
    
    
    LXModel *model =  self.MyArray[row];
    
    LXModel *tempModel = [[LXModel alloc]init];
    
    tempModel.alias = model.alias;

    tempModel.number = model.number;
    

    //选中按钮  选中状态
    tempModel.isBtnSelect = YES;
    
    
    NSInteger  tempNumber = [tempModel.number integerValue];
    tempNumber++;
    tempModel.number = [NSString stringWithFormat:@"%ld",tempNumber];
  
    //   替换
    [self.MyArray replaceObjectAtIndex:row withObject:tempModel];
    
  //计算总价格
    _zongHeLabel.text = [self ZongHeJiSuan:self.MyArray];
    
    
    [self.mainTableView reloadData];
}



// 减号  代理  方法
- (void)jianButtonDelegate:(NSInteger)row{

    LXModel *model =  self.MyArray[row];
    
    LXModel *tempModel = [[LXModel alloc]init];
    
    tempModel.alias = model.alias;
    
    tempModel.number = model.number;
    
    
    NSInteger reduce  = [tempModel.number integerValue];
    reduce--;
    tempModel.isBtnSelect = YES;
   
        if (reduce <= 0 ) {
            reduce = 0 ;
          tempModel.isBtnSelect = NO;
        }
    
    tempModel.number = [NSString stringWithFormat:@"%ld",reduce];
    //替换
    [self.MyArray replaceObjectAtIndex:row withObject:tempModel];
    // 计算总价格
    _zongHeLabel.text = [self ZongHeJiSuan:self.MyArray];
    
    [self.mainTableView reloadData];
}

</br>

第三个功能:

把cell 上的数字加到一个数组中,然后用valueForKeyPath 计算数组和

这里价格是写死的,不一样的时候 先让数量 乘以 价格 得出 单独商品价格,再把单独商品价格 加到数组中,计算总和

#pragma mark ===== 总和计算
- (NSString *)ZongHeJiSuan:(NSMutableArray *)arrary{
    
    NSMutableArray *arr = [NSMutableArray array];
    for (int i = 0; i < arrary.count; i++) {
        LXModel *model = arrary[i];
      
        [arr addObject:[NSString stringWithFormat:@"%ld",model.DanGeJiaGe * [model.number integerValue]]];
        
    }
    // 计算 数组之和
    NSNumber *sum = [arr valueForKeyPath:@"@sum.self"];
    
    return  [NSString stringWithFormat:@"%@",sum];
}

</br>

第四个功能:

主要需要注意价格计算,有数量的不需要再加需要记录下来,没有数量的加1
我的解决办法是 分成两部分,一部分加不为0的,一部分加为0的,最后加到一起乘以价格得出总价格

// 全选方法
- (void)allSelectBtnAction:(UIButton *)btn{
    //  之前有数值的
    NSInteger a = 0;
    //   之前没有数值的
    NSInteger b = 0;
    
    for (int i = 0 ; i < self.MyArray.count ; i++){

        LXModel *model =  self.MyArray[i];

        LXModel *tempModel = [[LXModel alloc]init];
        
        tempModel.alias = model.alias;
        
        if (btn.selected == YES){

            tempModel.isBtnSelect = YES;

            NSInteger  tempNumber = [model.number integerValue];
      
            if (tempNumber == 0){
                b++ ;
               tempModel.number = [NSString stringWithFormat:@"1"];
            } else  {
                tempModel.number = model.number;
                
                a = a + tempNumber;
            }
            
            tempNumber = b + a;
            
            _zongHeLabel.text = [NSString stringWithFormat:@"%ld",(b + a) * tempModel.DanGeJiaGe];

        } else {
          // 取消 全选
            tempModel.isBtnSelect = NO;
            
            NSInteger  tempNumber = 0;

            tempModel.number = [NSString stringWithFormat:@"%ld",tempNumber];
            _zongHeLabel.text = @"0";
        }

        //替换
        [self.MyArray replaceObjectAtIndex:i withObject:tempModel];
    }
    
       [self.mainTableView reloadData];
    
    // 点击  切换  button   状态
    if (btn.selected == YES){
        btn.selected = NO;
    
    } else {
        btn.selected = YES;
    }
    
}

</br>

第五部分

主要是使用数据库用到了FMDB,先创建一个单例

.h

Paste_Image.png

.m
创建单例

+ (instancetype)ShareDataBase{
    static dispatch_once_t  onceToKen;
    dispatch_once(&onceToKen,^{
        if (ShareDB == nil) {
            ShareDB = [[DataBase alloc]init];
            [ShareDB initDataBase];
        }
    });
    return ShareDB;
}


// 重写 allocWithZone   保证单例 唯一性
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
    if(ShareDB == nil){
        ShareDB = [super allocWithZone:zone];
    }
    return ShareDB;
}

- (id)copyWithZone:(NSZone *)zone{
    
    return self;
}

创建数据库 图片转成二进制 blob 类型 取出时为 data 类型

- (void)initDataBase{
    // 获得Documents目录路径
    
    NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    
    // 文件路径   数据库 名
    NSString *filePath = [documentsPath stringByAppendingPathComponent:@"GWCmodel.sqlite"];
    
    
    // 实例化FMDataBase对象
    // 得到数据库
    self.db = [FMDatabase databaseWithPath:filePath];
    
    //打开数据库
    if ([_db open]){
     
        
        // 创建数据库  id 主键 自增   网易新闻字符串  商品选中数量  价格   图片
        BOOL result = [self.db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_shopping (id integer PRIMARY KEY AUTOINCREMENT,WYString text NOT NULL,Numer text NO NULL , Price integer NOT NULL , Picture blob NO NULL);"];
        if(result){
            NSLog(@"创表成功");
            //一定要使用缓存,减少时间复杂度
            [_db shouldCacheStatements];
            
        }else{
            NSLog(@"创表失败");
        } 
    }
}

插入数据
谓词查询 http://www.jianshu.com/p/f63107b3c177

- (void)addDataBase:(LXModel *)model{
    // 打开数据库
    [_db open];
    
    //  根据  字符串 判断数据库中是否存在
    FMResultSet *resultSet = [self.db executeQuery:@"SELECT * FROM t_shopping where WYString = ?",model.alias];
    
    //2 遍历结果
    if([resultSet next]){

    // SET 更新内容   WHERE  判断条件   如果model.number 即数量不一样  就更新
       [_db executeUpdate:@"UPDATE t_shopping SET Numer = ?  WHERE WYString = ? ",model.number,model.alias];

    }else {
        // 不存在  插入新数据
        
     BOOL bResult =   [_db executeUpdateWithFormat:@"INSERT INTO t_shopping (WYString,Numer,Price,Picture) VALUES (%@ ,%@ ,%ld,%@);",model.alias,model.number,model.DanGeJiaGe,model.picture];
    
        if(bResult) {
            NSLog(@"数据插入成功!");
        }
        else {
            NSLog(@"数据插入失败!");
        }
    }
}

删除数据

- (void)deleteDataBase:(LXModel *)model{
    
    [_db open];
    // 根据 网易字符串  判断
    [_db executeUpdate:@"DELETE FROM t_shopping WHERE WYString = ?",model.alias];
}

获取所有数据

- (NSMutableArray *)getAllData{
    [_db open];
    
    NSMutableArray *dataArray = [[NSMutableArray alloc] init];
    
    FMResultSet *res = [_db executeQuery:@"SELECT * FROM t_shopping"];
    
    while ([res next]) {
        LXModel *model = [[LXModel alloc] init];
        
        model.alias = [res stringForColumn:@"WYString"];

        model.DanGeJiaGe = [[res stringForColumn:@"Price"]integerValue];
        
        model.number = [res stringForColumn:@"Numer"] ;
        
        model.picture = [res dataForColumn:@"Picture"];
 
        
        [dataArray addObject:model];
    
    }
    return dataArray;
}

</br>

第六部分

可以确定cell 高度时 这么写可以 不需要代理 提高执行效率
_mainTableView.rowHeight = 230;

</br>
监听 tf 变化 正则表达式

- (void)textFieldDidChange:(UITextField *)tf{
    
    if ([self checkForNumber:tf.text] ){
        
    } else {
        // 防止崩溃
        if (tf.text.length > 0){
            //  不匹配删掉  字符串最后一位
            tf.text = [tf.text substringToIndex:tf.text.length - 1];
        }
    }
}


//   只能输入数字  开头不能为0
- (BOOL)checkForNumber:(NSString *)number{
    //转意符  \d  \\d
    NSString *regEx = @"^[1-9]\\d*$";
    return [self baseCheckForRegEx:regEx data:number];
}


// 检测 正则表达式
- (BOOL)baseCheckForRegEx:(NSString *)regEx data:(NSString *)data{
    
    //谓词查询
    NSPredicate *card = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regEx];
    // 判断是否匹配
    if (([card evaluateWithObject:data])) {
        return YES;
    }
    return NO;
}

收藏按钮点击事件,根据是否选中判断加入数据库

- (void)reckonButtonAction{

    // 打开数据库
    [DataBase ShareDataBase];
    
    ShouCangVController *sc = [[ShouCangVController alloc]init];
    
    for (int i = 0 ; i < self.MyArray.count ; i++){
        LXModel *model = self.MyArray[i];
    
        if (model.isBtnSelect == YES){

        [[DataBase ShareDataBase]addDataBase:model];
            
        }
    }
    [self.navigationController pushViewController:sc animated:YES];
}

</br>
其实都不难,一个功能一个功能的实现就好,有什么问题请留言

上一篇 下一篇

猜你喜欢

热点阅读