開(kāi)篇
之前寫了幾篇商城相關(guān)的,規(guī)格選擇,小控件什么的儡遮,今天放一個(gè)購(gòu)物車的代碼和實(shí)現(xiàn)邏輯,也算對(duì)商城系列有個(gè)結(jié)尾吧暗赶。
商城系列文章:
iOS走近商城APP(一)
iOS走近商城APP(二 購(gòu)物車常用控件)
iOS走近商城APP(三 WKWebView 商品規(guī)格選擇框架封裝)
iOS走近商城APP(四 runloop應(yīng)用 獲取通訊錄并處理)
本篇文章主要內(nèi)容
購(gòu)物車的數(shù)據(jù)結(jié)構(gòu)的分析
購(gòu)物車的選中處理邏輯
購(gòu)物車的數(shù)量變化與價(jià)格計(jì)算
購(gòu)物車的商品刪除與數(shù)據(jù)刷新
購(gòu)物車的狀態(tài)峦萎、價(jià)格刷新的公共方法
購(gòu)物車的數(shù)據(jù)結(jié)構(gòu)的分析
由圖可以看到屡久,所有的數(shù)據(jù)是包含在一個(gè)大的數(shù)組內(nèi)的,大的數(shù)組內(nèi)又包含根據(jù)不同的商家區(qū)分的不同一級(jí)數(shù)組爱榔,每級(jí)數(shù)組里對(duì)應(yīng)的是包含各個(gè)商品的數(shù)據(jù)被环。為了方便做處理,對(duì)一個(gè)商品數(shù)據(jù)加入
[dict setObject:@NO forKey:@"checked"];
[dict setObject:@NO forKey:@"checkedSection"];
checked表示商品的是否選中的標(biāo)識(shí)详幽,checkedSection標(biāo)識(shí)組是否選中的標(biāo)識(shí)筛欢,默認(rèn)置為NO。構(gòu)造一個(gè)新的數(shù)據(jù)源來(lái)進(jìn)行操作唇聘。
購(gòu)物車的選中處理邏輯
首先是cell左側(cè)按鈕的選擇版姑,同時(shí)設(shè)置一個(gè)臨時(shí)參數(shù),遍歷當(dāng)前組的時(shí)候做自加運(yùn)算迟郎,如果最后數(shù)字等于組內(nèi)數(shù)據(jù)條數(shù)證明全部被選中剥险,設(shè)置組選中標(biāo)識(shí)的屬性。如果點(diǎn)擊的是組上的按鈕宪肖,遍歷數(shù)據(jù)表制,把所有的行選中狀態(tài)置為和組選中相同。同時(shí)走價(jià)格和選中狀態(tài)檢查的公共方法控乾。全選也是同理么介,主要的是每次做完操作都要走公共的價(jià)格和狀態(tài)更新方法。
#pragma mark -點(diǎn)擊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];//獲取當(dāng)前組內(nèi)的數(shù)組
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 -點(diǎn)擊組頭試圖
-(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];
}
}
實(shí)現(xiàn)的效果如下:
購(gòu)物車的數(shù)量變化與價(jià)格計(jì)算
數(shù)量的變化控件是單獨(dú)封裝的一個(gè)View蜕衡,加到cell通過(guò)cell上的代理處理相關(guān)的點(diǎn)擊操作壤短,判斷當(dāng)數(shù)字小于1的時(shí)候不允許繼續(xù)減少。在每次加減的時(shí)候控制中間的數(shù)量控件變化的同時(shí)要改變model中對(duì)應(yīng)價(jià)格的字段的數(shù)值慨仿,以便能夠重新計(jì)算價(jià)格久脯。
#pragma mark -加減按鈕 協(xié)議方法
//加
-(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];
}
實(shí)現(xiàn)效果如下:
購(gòu)物車的商品刪除與數(shù)據(jù)刷新
商品的刪除首先要存儲(chǔ)到想要?jiǎng)h除的數(shù)據(jù),同時(shí)符合選中狀態(tài)切是右上角按鈕狀態(tài)是編輯狀態(tài)的信息存儲(chǔ)到一個(gè)數(shù)組內(nèi)镰吆。比如我們存儲(chǔ)一個(gè)商品的訂單號(hào)id來(lái)作為刪選標(biāo)識(shí)帘撰。
#pragma mark -結(jié)算按鈕
-(void)clickMakeSureBtn{
if (self.rightTopBtn.selected) {//刪除相關(guān)選中商品
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) {
//把要?jiǎng)h除的數(shù)據(jù)存進(jìn)一個(gè)數(shù)組
[deleteGoodsArray addObject:goodsModel.goods_sn];
[self deletaGoods];//刪除數(shù)據(jù)
}else{
[self deletaGoods];
}
}
}
}else{//結(jié)算相關(guān)選中商品
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) {
//得到選中的數(shù)據(jù)信息
}
}
}
}
}
商品信息的刪除,這里采用的不是刪除二維數(shù)組的對(duì)應(yīng)坐標(biāo),而是遍歷整個(gè)數(shù)據(jù)源鼎姊,判斷如果我們用以保存刪除數(shù)據(jù)的數(shù)組deleteGoodsArray內(nèi)部是否包含當(dāng)前遍歷數(shù)據(jù)的id骡和,如果不包含,就把他添加到一個(gè)新的數(shù)據(jù)源中相寇,這樣慰于,遍歷結(jié)束,我們得到的一個(gè)新的數(shù)據(jù)源就是所有不包含刪除數(shù)據(jù)的數(shù)據(jù)源數(shù)組唤衫,這是用它來(lái)替換原來(lái)的數(shù)據(jù)源數(shù)據(jù)婆赠,刷新列表,實(shí)現(xiàn)數(shù)據(jù)的刪除。
#pragma mark -處理刪除數(shù)據(jù) 排除要?jiǎng)h除信息后新造一個(gè)數(shù)據(jù)源
-(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];
}
實(shí)現(xiàn)效果如下:
購(gòu)物車的狀態(tài)休里、價(jià)格刷新的公共方法
公共方法主要是兩個(gè)蛆挫,用以遍歷選中狀態(tài)和每次操作后的價(jià)格數(shù)據(jù)刷新。
#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 - 價(jià)格的計(jì)算
-(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];
}
核心基本就是這些了妙黍,這樣我們就簡(jiǎn)單實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的小購(gòu)物車的邏輯悴侵。至于一些加入購(gòu)物車的過(guò)期商品,下架商品的處理邏輯拭嫁,以后有機(jī)會(huì)了再慢慢更新到git上吧可免。只是為了實(shí)現(xiàn)一個(gè)簡(jiǎn)單的功能,有些地方可能寫的不夠簡(jiǎn)潔和規(guī)范做粤,主要是希望總結(jié)下思路練練手浇借。有不好的地方多包涵,下面里面放上git地址怕品,千萬(wàn)別說(shuō)故意不放代碼妇垢,哈哈
git地址,喜歡的star一下??
代碼在這里,看這里:
購(gòu)物車項(xiàng)目代碼ShopCartTest
后記
搞了一年多的商城肉康,也寫了幾篇多多少少和項(xiàng)目有關(guān)的文章闯估,最后還是補(bǔ)上了購(gòu)物車,畢竟沒(méi)有購(gòu)物車的商城不叫真正的商城迎罗,哈哈睬愤。接下來(lái)估計(jì)要轉(zhuǎn)入新項(xiàng)目片仿,看看有沒(méi)有機(jī)會(huì)寫一個(gè)別的系列吧纹安,這些文章算是自己的一個(gè)小小的總結(jié)吧,也希望對(duì)有需要的同學(xué)有所幫助砂豌。