不论是去做一个购物软件,或是其他软件,有购物车或者类似于购物车的页面都是很常见的。
常见的购物车一般可分存本地和存服务器。存在哪里对于我们客户端的开发其实差别不大。
以存储在本地为例,我们可以使用数据库来做,如果数据结构并不复杂,也可以使用NSUserDefaults来存储一个数组,但切记不要传入空。
我们以这样子简单的界面效果为例:
每一行左边有一个按钮可以来选择,也可以进行全选操作。
我们可以吧每一行的按钮用一个自定义的UIButton来布局,可以给这个button添加一个属性用来记录他所在的行号。
为了简化操作,我们给全选按钮添加监听,来区分选中状态和默认状态,就像这样。
在viewdidload中加入这样的代码:
[objc] view plain copy[_allChooseButton addObserver:self forKeyPath:@"buttonState" options:NSKeyValueObservingOptionNew context:@"_allChooseButtonStateChange"]; 并实现它的回调方法:[objc] view plain copy- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(voidvoid *)context { if (context == @"_allChooseButtonStateChange") { if (_allChooseButton.buttonState == ButtonStateNormal) { [_allChooseButton setBackgroundImage:[UIImage imageNamed:@"goods_n"] forState:UIControlStateNormal]; }else { [_allChooseButton setBackgroundImage:[UIImage imageNamed:@"goods_s"] forState:UIControlStateNormal]; } } }接下来,我们需要完成选中,未选中,全选,等状态的判断和存储。
我们可以准备一个全局的可变数组并初始化,用来存储所有数据每一个的选中状态。
[objc] view plain copy_allCellStateArray = [[NSMutableArray alloc]init]; 并将我们的数据每一个对象的选中状态存入数组,或者说每一行的状态,我们让他默认不被选中:[objc] view plain copyfor (int i = 0; i < _resultValue.count; i ++) { NSMutableDictionary *dic = [[NSMutableDictionary alloc]init]; [dic setValue:@"0" forKey:[NSString stringWithFormat:@"%ld",(long)i]]; [_allCellStateArray addObject:dic]; } 存入的字典的key为当前的行号,value为选中状态,我们用1表示被选中,0表示未被选中。当我们点击全选按钮时,按钮的图片会发生变化,并且选中状态也会发生变化,先在cellforrow方法中加入代码:
[objc] view plain copycell.chooseButton.indexNumber = indexPath.row; if ([[[_allCellStateArray objectAtIndex:indexPath.row] objectForKey:[NSString stringWithFormat:@"%ld",(long)indexPath.row]] intValue]==0) { // 当value为0时,按钮的状态为不选中 cell.chooseButton.buttonState = ButtonStateNormal; }else { cell.chooseButton.buttonState = ButtonStateClicked; } if (cell.chooseButton.buttonState == ButtonStateNormal) { // 当状态为不选中时 [cell.chooseButton setBackgroundImage:[UIImage imageNamed:@"goods_n"] forState:UIControlStateNormal]; }else { // 当状态为选中时 [cell.chooseButton setBackgroundImage:[UIImage imageNamed:@"goods_s"] forState:UIControlStateNormal]; } [cell.chooseButton addTarget:self action:@selector(cellChooseClick:) forControlEvents:UIControlEventTouchUpInside]; 上面两段代码可以写到一个if语句中。当我们点击按钮时,我们要改变按钮的状态,并且要将存放我们状态的数组做修改。
[objc] view plain copy#PRagma mark - 选择 - (void)cellChooseClick:(EMButton *)sender { if (sender.buttonState == ButtonStateNormal) { NSMutableDictionary *dic = [[NSMutableDictionary alloc]init]; [dic setValue:@"1" forKey:[NSString stringWithFormat:@"%ld",(long)sender.indexNumber]]; [_allCellStateArray replaceObjectAtIndex:sender.indexNumber withObject:dic]; BOOL isAll = YES; for (int i = 0; i < _allCellStateArray.count; i ++) { int a = [[[_allCellStateArray objectAtIndex:i] objectForKey:[NSString stringWithFormat:@"%d",i]] intValue]; if (a == 0) { isAll = 0; } } if (isAll) { _allChooseButton.buttonState = ButtonStateClicked; } }else { _allChooseButton.buttonState = ButtonStateNormal; NSMutableDictionary *dic = [[NSMutableDictionary alloc]init]; [dic setValue:@"0" forKey:[NSString stringWithFormat:@"%ld",(long)sender.indexNumber]]; [_allCellStateArray replaceObjectAtIndex:sender.indexNumber withObject:dic]; } NSIndexPath *indexPath=[NSIndexPath indexPathForRow:sender.indexNumber inSection:0]; [self.mainTable reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath,nil] withRowAnimation:UITableViewRowAnimationMiddle]; } 中间的bool判断是用来实现:当用户在未全选状态下,选择了所有行,全选按钮变为全选状态;当用户点击了全选按钮进入全选状态,后又将其中一行取消选择,则全选状态取消。如图:至此,所有的选择取消逻辑就完成了,不管是点击了提交按钮来获取选择的对象,还是在下方显示商品数量和价格。我们都可以通过保存每行数据状态的数组来在我们的数据源中取对象。
[objc] view plain copy#pragma mark - 提交按钮 - (void)submitMethod:(EMButton *)sender { NSMutableArray *array = [[NSMutableArray alloc]init]; for (int i = 0; i < _allCellStateArray.count; i ++) { if ([[[_allCellStateArray objectAtIndex:i] objectForKey:[NSString stringWithFormat:@"%d",i]] intValue]==1) { [array addObject:[_resultValue objectAtIndex:i]]; } } NSLog(@"submit:%@ %ld",array,(long)array.count); } 用来改变下方的商品数量的方法:[objc] view plain copy- (void)changeInfoLabel { NSMutableArray *array = [[NSMutableArray alloc]init]; for (int i = 0; i < _allCellStateArray.count; i ++) { if ([[[_allCellStateArray objectAtIndex:i] objectForKey:[NSString stringWithFormat:@"%d",i]] intValue]==1) { [array addObject:[_resultValue objectAtIndex:i]]; } } _countNumber = (int)array.count; _money = 0; for (int i = 0;i < array.count; i ++) { _money += [[[array objectAtIndex:i] objectForKey:@"buyNum"] intValue]; } _tabInfoLabel.text = [NSString stringWithFormat:@"共%d件商品,共%d元",_countNumber,_money]; NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:_tabInfoLabel.text]; UIColor * color1 = [UIColor colorWithRed:214.0/255.0 green:74.0/255.0 blue:115.0/255.0 alpha:1.0] ; [str addAttribute:NSForegroundColorAttributeName value:color1 range:NSMakeRange(1,[NSString stringWithFormat:@"%d",_countNumber].length)]; [str addAttribute:NSForegroundColorAttributeName value:color1 range:NSMakeRange(1+[NSString stringWithFormat:@"%d",_countNumber].length+5,[NSString stringWithFormat:@"%d",_money].length)]; [str addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"Helvetica" size:16.0] range:NSMakeRange(1, 2)]; _tabInfoLabel.attributedText = str; } 我们可以在全选按钮的方法,单选按钮的方法中调用此方法,这样在我们每次点击的时候,都能时刻改变下方的数量价格信息。我们的购物车基本上就写好啦。
如果想加入加减某个商品的数量,或者删除某个商品的功能,如:
那我们就需要多加一些判断了,比如加减按钮,并不会影响到我们存放每行选中状态的数组,这个改变的是数据源,我们需要实时的改变我们原来在本地存储的数据源(也可以在退出购物车页面的时候统一存储,但如果用户在此页面时退出程序,便无法存储新修改的数据)。
删除功能需要我们修改数据文件的同时,也不要忘记同时需要修改状态数组。这样子,我们的购物车又多了两个新功能。
如果你的购物车数据是从服务器下载的,道理和存本地一样,只是我们不能时时修改数据文件,这里我们最好还是在离开此页面时同意修改,否则会很费流量。
最后,总结一下最核心的部分:将数据源的每一条数据存成一个独立的字典,key为行号,value为选中状态,并将这些字典存入一个数组中。
先说这么多吧,本人经验尚浅,有更好建议的欢迎留言。
新闻热点
疑难解答