iOS - 購物車界面的實(shí)現(xiàn)

在商城類APP的開發(fā)中婿斥,購物車功能是必不可少的。
在上一個(gè)app的開發(fā)中生活又對(duì)我這個(gè)菜鳥下手了哨鸭,我被安排實(shí)現(xiàn)購物車功能WTF ~.~ .吐槽歸吐槽受扳,功能還是要實(shí)現(xiàn)滴。兔跌。。

購物車

實(shí)現(xiàn)思路:

  1. 購物車界面實(shí)現(xiàn)的關(guān)鍵是對(duì)MVC模式開發(fā)的理解和運(yùn)用峡蟋。我們通過在Model中定義一個(gè)是否被選中的bool值(isSelect)來改變選擇的狀態(tài)坟桅。
    其實(shí)MVC這種運(yùn)用場景還是很多的,比如我們要?jiǎng)討B(tài)計(jì)算一個(gè)cell的高度的時(shí)候蕊蝗,我們通常也是會(huì)在model中去進(jìn)行計(jì)算仅乓,然后將結(jié)果通過一個(gè)定義的常量暴露在.h文件中供其他調(diào)用。
  2. 自定義cell蓬戚,這個(gè)就不多說了夸楣,不管是復(fù)雜的還是簡單的cell大多數(shù)都是自定義的,這里復(fù)雜的數(shù)據(jù)可能用到富文本子漩,比如這里現(xiàn)價(jià)和市場價(jià)我是一個(gè)label然后用富文本實(shí)現(xiàn)的豫喧。
  3. 多選的實(shí)現(xiàn)是在controller中聲明了一個(gè)選中的數(shù)組,然后將選中的model保存到可變數(shù)組中幢泼。
  4. 代理的運(yùn)用紧显。這個(gè)功能使用到了很多代理的思想,底部結(jié)算區(qū)也是用代理實(shí)現(xiàn)的缕棵。(不建議用block孵班,就是代理和block的優(yōu)缺點(diǎn)比較吧)涉兽。

下面是代碼的實(shí)現(xiàn):

ShoppingCartModel.h

#import <Foundation/Foundation.h>

@interface ShoppingCartModel : NSObject
/**購物車ID*/
@property(nonatomic,strong)NSString *cartId ;

/**商品的編號(hào)*/
@property(nonatomic,strong)NSString *goodsNo ;

/**商品的id*/
@property(nonatomic,strong)NSString *goodsId ;

/**商品的圖片*/
@property(nonatomic,strong)NSString *goodsImage ;

/**商品的名稱*/
@property(nonatomic,strong)NSString *goodsName ;

/**商品的的市場價(jià)格*/
@property(nonatomic,strong)NSString *goodsMarketPrice ;

/**商品價(jià)格*/
@property(nonatomic,strong)NSString *goodsSystemPrice ;

/**商品的市場價(jià)格*/
@property(nonatomic,assign)NSInteger number ;

/**上次是否被選*/
@property (nonatomic, assign) BOOL isSelect;

-(instancetype)initWithDict:(NSDictionary *)dict ;
+(instancetype)ShoppingCartModelWithDict:(NSDictionary *)dict ;

@end

自定義cell聲明代理方法
ShoppingCartTableViewCell.h

#import <UIKit/UIKit.h>
#import "ChoiceButton.h"

@class ShoppingCartTableViewCell,ShoppingCartModel,SureFormModel ;

@protocol ShoppingCartTableViewDelegate <NSObject>

@optional

/**選中*/
- (void)shopCartGoodViewCell:(ShoppingCartTableViewCell *)cell withSelectedModel:(ShoppingCartModel *)model;

/**添加、減少*/
- (void)shopCartGoodViewCellChange:(ShoppingCartTableViewCell *)cell ;

/**輸入框事件*/
- (void)shopCartGoodViewCellTextField:(ShoppingCartTableViewCell *)cell;

@end

@interface ShoppingCartTableViewCell : UITableViewCell

/** 代理屬性 */
@property (nonatomic ,weak)id<ShoppingCartTableViewDelegate>  delegate;

@property(nonatomic,strong) ShoppingCartModel *model ;

@end

這里完成cell的布局篙程,就不貼代碼了枷畏,主要是代理部分的代碼
ShoppingCartTableViewCell.m

#pragma mark - 勾選按鈕事件
-(void)choiceButtonAction:(UIButton *)button{
    
    ShoppingCartTableViewCell *cell = (ShoppingCartTableViewCell *)button.superview.superview;
    
    if ([self.delegate respondsToSelector:@selector(shopCartGoodViewCell:withSelectedModel:)]) {
        [self.delegate shopCartGoodViewCell:cell withSelectedModel:cell.model];
    }
}

#pragma mark - 商品數(shù)量的setter方法
- (void)setGoodsCount:(NSInteger)goodsCount{
    _goodsCount = goodsCount;
    _shopNumberTextField.text = [NSString stringWithFormat:@"%ld", (long)goodsCount] ;
}

#pragma mark - textFieldDelegete
-(void)textFieldDidEndEditing:(UITextField *)textField{
    ShoppingCartTableViewCell *cell = (ShoppingCartTableViewCell *)textField.superview.superview.superview;
    ShoppingCartModel *model = cell.model;
    
    if ([_shopNumberTextField.text integerValue] >= 99) {
        self.shopNumberTextField.text = [NSString stringWithFormat:@"%d", 99];
    }
    if ([_shopNumberTextField.text integerValue] <= 0) {
        self.shopNumberTextField.text = [NSString stringWithFormat:@"%d", 1];
    }
    
    model.number = [self.shopNumberTextField.text integerValue];
    //向服務(wù)器發(fā)送請(qǐng)求
    [self.delegate shopCartGoodViewCellTextField:self];
}


#pragma mark - 減按鈕事件
-(void)minusButtonAction:(UIButton *)button{
    ShoppingCartTableViewCell *cell = (ShoppingCartTableViewCell *)button.superview.superview.superview;
    ShoppingCartModel *model = cell.model;
    if (_goodsCount != 1) {
        self.goodsCount = self.goodsCount - 1;
        model.number = self.goodsCount;
        //向服務(wù)器發(fā)送請(qǐng)求
        [self.delegate shopCartGoodViewCellChange:self];
    }
    
}

#pragma mark - 加按鈕事件
-(void)plusButtonAction:(UIButton *)button{
    ShoppingCartTableViewCell *cell = (ShoppingCartTableViewCell *)button.superview.superview.superview;
    ShoppingCartModel *model = cell.model;
    
    //換成最大庫存
    if (_goodsCount <= 99) {
        self.goodsCount = self.goodsCount + 1;
        model.number = self.goodsCount;
    }else{
        self.goodsCount = 99;
        model.number = self.goodsCount;
    }
    //向服務(wù)器發(fā)送請(qǐng)求
    [self.delegate shopCartGoodViewCellChange:self];
    
}

底部結(jié)算區(qū):
ShoppingCartBottomMenuView.h

#import <UIKit/UIKit.h>
#import "ChoiceButton.h"

NS_ASSUME_NONNULL_BEGIN

@class ShoppingCartBottomMenuView ;

@protocol ShoppingCartBottomMenuViewDelegate <NSObject>

-(void)shoppingCartbottomPriceView:(ShoppingCartBottomMenuView *)bottonView;
/**
 付款
 */
-(void)shoppingCartPayAccountsButton:(ShoppingCartBottomMenuView *)bottonView;
/**
 刪除
 */
-(void)shoppingCartDeleteButton:(ShoppingCartBottomMenuView *)bottonView;

@end

@interface ShoppingCartBottomMenuView : UIView

@property(nonatomic,strong)ChoiceButton *choiceButton ; //全選

@property(nonatomic,strong)UILabel *choiceLabel ; //選擇狀態(tài)

@property(nonatomic,strong)UILabel *totalPriceLabel ; //總價(jià)

@property(nonatomic,strong)UIButton *payAccountsButton ; //付款按鈕

@property(nonatomic,strong)UIButton *deleteButton ; //刪除按鈕

/**結(jié)算字符串*/
@property (nonatomic, copy) NSString *payStr;
/**合計(jì)字符串*/
@property (nonatomic, strong) NSString *attAllStr;
@property (nonatomic, strong) NSString *changeStr;
@property (nonatomic, assign) BOOL isSelectBtn ;

@property (weak, nonatomic) id<ShoppingCartBottomMenuViewDelegate> delegate;

@end

ShoppingCartBottomMenuView.m

- (void)setIsSelectBtn:(BOOL)isSelectBtn{
    _choiceButton.selected = isSelectBtn;
    if ([self.delegate respondsToSelector:@selector(shoppingCartbottomPriceView:)]) {
        [self.delegate shoppingCartbottomPriceView:self];
    }
}

- (void)choiceButtonAction:(UIButton *)button{
    button.selected = !button.isSelected;
    
    if (button.selected) {
        self.choiceLabel.text = @"全不選" ;
    }else{
        self.choiceLabel.text = @"全選" ;
    }

    if ([self.delegate respondsToSelector:@selector(shoppingCartbottomPriceView:)]) {
        [self.delegate shoppingCartbottomPriceView:self];
    }
}

-(void)payAccountsButtonAction{
    if ([self.delegate respondsToSelector:@selector(shoppingCartPayAccountsButton:)]) {
        [self.delegate shoppingCartPayAccountsButton:self];
    }
}

-(void)deleteButtonAction{
    if ([self.delegate respondsToSelector:@selector(shoppingCartDeleteButton:)]) {
        [self.delegate shoppingCartDeleteButton:self];
    }
}

- (void)setPayStr:(NSString *)payStr{
    _payStr = payStr ;
    
    if ([payStr isEqualToString:@""]) {
        [self.payAccountsButton setTitle:@"結(jié)算" forState:UIControlStateNormal];
    }else{
        [self.payAccountsButton setTitle:[NSString stringWithFormat:@"結(jié)算%@", payStr] forState:UIControlStateNormal];
    }
    
    
}

- (void)setAttAllStr:(NSString *)attAllStr{
    _attAllStr = [NSString stringWithFormat:@"合計(jì):¥%@", attAllStr];
    NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc]initWithString:_attAllStr];
    
    //添加屬性
    NSRange range = { 4,_attAllStr.length - 4};
    
    NSRange range1 = {3, _attAllStr.length - 3};
    
    [attStr addAttribute:NSFontAttributeName value:FONT(22 * kFitWithWidth) range:NSMakeRange(3, 1)] ;
    
    [attStr addAttribute:NSFontAttributeName value:FONT_BOLD(32 * kFitWithWidth) range:range];
    [attStr addAttribute:NSForegroundColorAttributeName value:RGB(247, 89, 64) range:range1];
    self.totalPriceLabel.attributedText = attStr;
}

在controller中
ShoppingCartViewController.m

/**選中的商品模型數(shù)組*/
@property(nonatomic,strong)NSMutableArray *selectedArray ;

/**底部結(jié)算區(qū)*/
@property(nonatomic,strong)ShoppingCartBottomMenuView *menuView ;

/**總價(jià)格*/
@property (nonatomic, assign) double allSum ;

#pragma mark - ShoppingCartTableViewDelegate
/**添加、減去*/
- (void)shopCartGoodViewCellChange:(ShoppingCartTableViewCell *)cell{
    _allSum = 0;
    for (ShoppingCartModel *model in self.selectedArray) {
        self.allSum += [model.goodsSystemPrice floatValue] * model.number ;
        
    }
    _menuView.attAllStr = [NSString stringWithFormat:@"%.2f", self.allSum];

    [self insertOrUpdateShoppingCar:cell] ;

}

- (void)shopCartGoodViewCellTextField:(ShoppingCartTableViewCell *)cell{
    _allSum = 0;
    for (ShoppingCartModel *model in self.selectedArray) {
        self.allSum += [model.goodsSystemPrice floatValue] * model.number ;
    }
    _menuView.attAllStr = [NSString stringWithFormat:@"%.2f", self.allSum];
    
    [self insertOrUpdateShoppingCar:cell] ;
}

/**選中*/
- (void)shopCartGoodViewCell:(ShoppingCartTableViewCell *)cell withSelectedModel:(ShoppingCartModel *)model{
    
    if ([self.selectedArray containsObject:model]) {
        [self.selectedArray removeObject:model];
        //每當(dāng)取消選中商品
        self.menuView.choiceButton.selected = NO;
        model.isSelect = NO;
        
        self.allSum -= [model.goodsSystemPrice floatValue] * model.number;
    }else{
        //選中之后
        [self.selectedArray addObject:model];
        model.isSelect = YES;
        
        self.allSum += [model.goodsSystemPrice floatValue] * model.number;
    }
    
    if (self.selectedArray.count == self.shoppingCartListArray.count) {
        //全部店鋪添加
        self.menuView.choiceButton.selected = YES;
        self.menuView.choiceLabel.text = @"全不選" ;
    }else{
        self.menuView.choiceButton.selected = NO;
        self.menuView.choiceLabel.text = @"全選" ;
    }
    
    self.menuView.attAllStr = [NSString stringWithFormat:@"%.2f", self.allSum];
    
    if (self.selectedArray.count > 0) {
        self.menuView.payStr = [NSString stringWithFormat:@"(%lu)", self.selectedArray.count];
    }else{
        self.menuView.payStr = @"" ;
    }
    
    [self.shoppingCartTableView reloadData];

}

#pragma mark - ShoppingCartBottomMenuViewDelegate
//底部選中
-(void)shoppingCartbottomPriceView:(ShoppingCartBottomMenuView *)bottonView{
    if (bottonView.choiceButton.selected) {
        [self.selectedArray removeAllObjects];
        
        [self.selectedArray addObjectsFromArray:self.shoppingCartListArray];
        for (ShoppingCartModel *model in self.shoppingCartListArray) {
            model.isSelect = YES;
            
        }
        self.allSum = 0.0;
        //計(jì)算總價(jià)格
        for (ShoppingCartModel *model in self.selectedArray) {
            self.allSum += [model.goodsSystemPrice floatValue] * model.number;
        }
    }else{
        [self.selectedArray removeAllObjects];
        
        for (ShoppingCartModel *model in self.shoppingCartListArray) {
            model.isSelect = NO;
        }
        self.allSum = 0.0;
    }
    bottonView.attAllStr = [NSString stringWithFormat:@"%.2f", self.allSum];
    if (self.selectedArray.count > 0) {
        self.menuView.payStr = [NSString stringWithFormat:@"(%lu)", self.selectedArray.count];
    }else{
        self.menuView.payStr = @"" ;
    }
    [self.shoppingCartTableView reloadData];
    
}

大致思路就是這樣虱饿。我們就可以實(shí)現(xiàn)購物車功能了拥诡。
有不足的地方希望大家積極補(bǔ)充。共勉郭厌。袋倔。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市折柠,隨后出現(xiàn)的幾起案子宾娜,更是在濱河造成了極大的恐慌,老刑警劉巖扇售,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件前塔,死亡現(xiàn)場離奇詭異,居然都是意外死亡承冰,警方通過查閱死者的電腦和手機(jī)华弓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來困乒,“玉大人寂屏,你說我怎么就攤上這事∧嚷В” “怎么了迁霎?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長百宇。 經(jīng)常有香客問我考廉,道長,這世上最難降的妖魔是什么携御? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任昌粤,我火速辦了婚禮,結(jié)果婚禮上啄刹,老公的妹妹穿的比我還像新娘涮坐。我一直安慰自己,他們只是感情好誓军,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布膊升。 她就那樣靜靜地躺著,像睡著了一般谭企。 火紅的嫁衣襯著肌膚如雪廓译。 梳的紋絲不亂的頭發(fā)上评肆,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音非区,去河邊找鬼瓜挽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛征绸,可吹牛的內(nèi)容都是我干的久橙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼管怠,長吁一口氣:“原來是場噩夢啊……” “哼淆衷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起渤弛,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤祝拯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后她肯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體佳头,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年晴氨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了康嘉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡籽前,死狀恐怖亭珍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情枝哄,我是刑警寧澤肄梨,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站膘格,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏财松。R本人自食惡果不足惜瘪贱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望辆毡。 院中可真熱鬧菜秦,春花似錦、人聲如沸舶掖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽眨攘。三九已至主慰,卻和暖如春嚣州,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背共螺。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工该肴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人藐不。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓匀哄,卻偏偏與公主長得像,于是被迫代替她去往敵國和親雏蛮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子涎嚼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

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