iOS走近商城APP(五 購(gòu)物車)

開(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à)格刷新的公共方法


效果圖.png
購(gòu)物車的數(shù)據(jù)結(jié)構(gòu)的分析
數(shù)據(jù)結(jié)構(gòu).png

由圖可以看到屡久,所有的數(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)的效果如下:


選中.gif
購(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)效果如下:


價(jià)格變化.gif
購(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)效果如下:


刪除.gif
購(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ō)故意不放代碼妇垢,哈哈


否認(rèn)三連.jpg

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é)有所幫助砂豌。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末厢岂,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子阳距,更是在濱河造成了極大的恐慌塔粒,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件筐摘,死亡現(xiàn)場(chǎng)離奇詭異卒茬,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)咖熟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門圃酵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人馍管,你說(shuō)我怎么就攤上這事郭赐。” “怎么了确沸?”我有些...
    開(kāi)封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵捌锭,是天一觀的道長(zhǎng)俘陷。 經(jīng)常有香客問(wèn)我,道長(zhǎng)观谦,這世上最難降的妖魔是什么拉盾? 我笑而不...
    開(kāi)封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮豁状,結(jié)果婚禮上盾剩,老公的妹妹穿的比我還像新娘。我一直安慰自己替蔬,他們只是感情好告私,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著承桥,像睡著了一般驻粟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凶异,一...
    開(kāi)封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天蜀撑,我揣著相機(jī)與錄音,去河邊找鬼剩彬。 笑死酷麦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的喉恋。 我是一名探鬼主播沃饶,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼轻黑!你這毒婦竟也來(lái)了糊肤?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤氓鄙,失蹤者是張志新(化名)和其女友劉穎馆揉,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抖拦,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡升酣,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了态罪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片噩茄。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖向臀,靈堂內(nèi)的尸體忽然破棺而出巢墅,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布君纫,位于F島的核電站驯遇,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蓄髓。R本人自食惡果不足惜叉庐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望会喝。 院中可真熱鬧陡叠,春花似錦、人聲如沸肢执。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)预茄。三九已至兴溜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間耻陕,已是汗流浹背拙徽。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诗宣,地道東北人膘怕。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像召庞,于是被迫代替她去往敵國(guó)和親岛心。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,077評(píng)論 25 707
  • 導(dǎo)語(yǔ) 使用RAC實(shí)踐購(gòu)物車邏輯的梳理裁眯!首先分析ViewModel里面的每一個(gè)屬性鹉梨,然后分析ViewModel里面的...
    Carden閱讀 630評(píng)論 0 0
  • 心血來(lái)潮讳癌,突然想把自己這幾年的經(jīng)歷與感想記錄于《簡(jiǎn)書》穿稳。原因如下: 一、記錄自己的生活...
    一個(gè)口吃患者閱讀 153評(píng)論 0 0
  • 隨著人們生活水平的不斷提高晌坤,生活節(jié)奏的加快逢艘,人們可分配的時(shí)間越來(lái)越碎片化,而閱讀骤菠、咨詢類的APP則可以很好...
    Mis葳閱讀 724評(píng)論 0 2
  • 根據(jù)我們的統(tǒng)計(jì)分析它改,目前使用的人最多的教材是北京大學(xué)的《標(biāo)準(zhǔn)韓國(guó)語(yǔ)》,大的培訓(xùn)機(jī)構(gòu)傾向于使用韓國(guó)原版的教材商乎,如《新...
    韓語(yǔ)皎皎老師閱讀 720評(píng)論 0 0