不論是去做一個購物軟件,或是其他軟件,有購物車或者類似于購物車的頁面都是很常見的。
常見的購物車一般可分存本地和存服務器。存在哪里對于我們客戶端的開發其實差別不大。
以存儲在本地為例,我們可以使用數據庫來做,如果數據結構并不復雜,也可以使用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為選中狀態,并將這些字典存入一個數組中。
先說這么多吧,本人經驗尚淺,有更好建議的歡迎留言。
新聞熱點
疑難解答