Giter Site home page Giter Site logo

jsshopcartmodule's Introduction

JSShopCartModule

GitHub license GitHub license CocoaPods Compatible

开始之前你需要了解的

配置CocoaPods

安装CocoaPods命令

 gem install cocoapods   ##使用RVM安装的Ruby不需要sudo

配置ReactiveCocoa

然后在你的Podfile添加一下代码

platform :ios, '8.0'
use_frameworks!

target '你的项目工程名' do
   pod 'ReactiveObjC'
end

最后输入命令安装

pod install

另外常用的pod 命令

pod install --verbose --no-repo-update       ##安装不更新的
pod update --verbose --no-repo-update        ##更新需要更新的

打开 你的项目工程名.xcworkspace 即可~

RAC在此我就不仔细介绍了,先推荐几遍文章:

Mattt Thompson写的Reactive​Cocoa

Ash Furrow写的 Getting Started with ReactiveCocoa

了解MVVM

Google了看几篇有关的文章

Basic MVVM with ReactiveCocoa

MVVM-IOS-Example

MVVM 介绍 译 朱宏旭

简单的介绍一下:

M:model放一些数据模型

V:view视图

V:viewcontroller控制器

VM:viewmodel主要做处理逻辑和处理数据


开始着手代码

项目演示

image

<<<<<<< HEAD

项目搭建框架

整体文件目录按照模块分一下子文件

ViewController :
	ViewController				##加载视图事件监听等等
Model :
	model						##基本数据模型
View : 
	cell						##cell
	numbercount					##封装加减控件
	header						##店铺之类
	footer						##小结
	cartbar					    ##封装购物车底部view
ViewModel :
	service						##抽离tableview的datasource和delegate
	viewmodel				    ##处理主要的逻辑和数据

viewmodel类方法属性解析

获取数据方法

1.循环20个从0到5之间随机取数组里取值加到最终的cartData数组里 2.店铺选择shopSelectArray默认NO状态 3.统计总共购物车数量cartGoodsCount

- (void)getData{
    //数据个数
    NSInteger allCount = 20;
    NSInteger allGoodsCount = 0;
    NSMutableArray *storeArray = [NSMutableArray arrayWithCapacity:allCount];
    NSMutableArray *shopSelectAarry = [NSMutableArray arrayWithCapacity:allCount];
    //创造店铺数据
    for (int i = 0; i<allCount; i++) {
        //创造店铺下商品数据
        NSInteger goodsCount = [_shopGoodsCount[self.random] intValue];
        NSMutableArray *goodsArray = [NSMutableArray arrayWithCapacity:goodsCount];
        for (int x = 0; x<goodsCount; x++) {
            JSCartModel *cartModel = [[JSCartModel alloc] init];
            cartModel.p_id         = @"122115465400";
            cartModel.p_price      = [_goodsPriceArray[self.random] floatValue];
            cartModel.p_name       = [NSString stringWithFormat:@"%@这是一个很长很长的名字呀呀呀呀呀呀",@(x)];
            cartModel.p_stock      = 22;
            cartModel.p_imageUrl   = _goodsPicArray[self.random];
            cartModel.p_quantity   = [_goodsQuantityArray[self.random] integerValue];
            [goodsArray addObject:cartModel];
            allGoodsCount++;
        }
        [storeArray addObject:goodsArray];
        [shopSelectAarry addObject:@(NO)];
    }
    self.cartData = storeArray;
    self.shopSelectArray = shopSelectAarry;
    self.cartGoodsCount = allGoodsCount;
}

获取当前选中价格总和方法

对cartData数组转信号流然后map自定义需求return,期间自定义需求参数value 再次转信号流经过filter筛选未选中使isSelectAll为NO,然后经过map自定义需求使model.p_quantity*model.p_price得到的商品总价返回,最终return得到商品总价数组pricesArray.

快速遍历pricesArray得出总价allPrices

- (float)getAllPrices{
    
    __block float allPrices   = 0;
    NSInteger shopCount       = self.cartData.count;
    NSInteger shopSelectCount = self.shopSelectArray.count;
    if (shopSelectCount == shopCount && shopCount!=0) {
        self.isSelectAll = YES;
    }
    NSArray *pricesArray = [[[self.cartData rac_sequence] map:^id(NSMutableArray *value) {
        return [[[value rac_sequence] filter:^BOOL(JSCartModel *model) {
            if (!model.isSelect) {
                self.isSelectAll = NO;
            }
            return model.isSelect;
        }] map:^id(JSCartModel *model) {
            return @(model.p_quantity*model.p_price);
        }];
    }] array];
    for (NSArray *priceA in pricesArray) {
        for (NSNumber *price in priceA) {
            allPrices += price.floatValue;
        }
    }
    
    return allPrices;
}

全选yes or not

shopSelectArray转流map定义需求isSelect为YES的对象然后return 成可变数组.

cartData转流map定义需求,对其参数value转流map定义需求KVC使model的isSelect属性为YES,再次计算记录总价allPrices.return再return成可变数组.

- (void)selectAll:(BOOL)isSelect{
    
     __block float allPrices = 0;
    
    self.shopSelectArray = [[[[self.shopSelectArray rac_sequence] map:^id(NSNumber *value) {
        return @(isSelect);
    }] array] mutableCopy];
    self.cartData = [[[[self.cartData rac_sequence] map:^id(NSMutableArray *value) {
        return  [[[[value rac_sequence] map:^id(JSCartModel *model) {
                [model setValue:@(isSelect) forKey:@"isSelect"];
            if (model.isSelect) {
                allPrices += model.p_quantity*model.p_price;
            }
            return model;
        }] array] mutableCopy];
    }] array] mutableCopy];
    self.allPrices = allPrices;
    [self.cartTableView reloadData];
}

单行选择处理方法

KVC设置model的isSelect为YES,做店铺下商品选中满判断

- (void)rowSelect:(BOOL)isSelect IndexPath:(NSIndexPath *)indexPath{
    
    NSInteger section          = indexPath.section;
    NSInteger row              = indexPath.row;

    NSMutableArray *goodsArray = self.cartData[section];
    NSInteger shopCount        = goodsArray.count;
    JSCartModel *model         = goodsArray[row];
    [model setValue:@(isSelect) forKey:@"isSelect"];
    //判断是都到达足够数量
    NSInteger isSelectShopCount = 0;
    for (JSCartModel *model in goodsArray) {
        if (model.isSelect) {
            isSelectShopCount++;
        }
    }
    [self.shopSelectArray replaceObjectAtIndex:section withObject:@(isSelectShopCount==shopCount?YES:NO)];
    
    [self.cartTableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationNone];
    
    /*重新计算价格*/
    self.allPrices = [self getAllPrices];
}

单行数量处理方法

KVC处理model.再次调用getAllPrices方法计算总价

- (void)rowChangeQuantity:(NSInteger)quantity indexPath:(NSIndexPath *)indexPath{
    
    NSInteger section  = indexPath.section;
    NSInteger row      = indexPath.row;

    JSCartModel *model = self.cartData[section][row];

    [model setValue:@(quantity) forKey:@"p_quantity"];
    
    [self.cartTableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationNone];
    
    /*重新计算价格*/
    self.allPrices = [self getAllPrices];
}

左滑删除商品

数组删除,做店铺下商品删除完判断处理

- (void)deleteGoodsBySingleSlide:(NSIndexPath *)path{
    
    NSInteger section = path.section;
    NSInteger row     = path.row;
    
    NSMutableArray *shopArray = self.cartData[section];
    [shopArray removeObjectAtIndex:row];
    if (shopArray.count == 0) {
        /*1 删除数据*/
        [self.cartData removeObjectAtIndex:section];
        /*2 删除 shopSelectArray*/
        [self.shopSelectArray removeObjectAtIndex:section];
        [self.cartTableView reloadData];
    } else {
        [self.cartTableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationNone];
    }
    self.cartGoodsCount-=1;
    /*重新计算价格*/
    self.allPrices = [self getAllPrices];
}

删除选中处理方法

创建可变集合shopSelectIndex,遍历cartData,遍历shopArray,取得选中的index2加到selectIndexSet中,做店铺count和选中商品相等判断,index1加到shopSelectIndex中,cartGoodsCount做递减处理,然后依次shopArray做删除操作,cartData在循环外删除操作,shopSelectArray在循环外删除操作,价格为0,重新计算价格

- (void)deleteGoodsBySelect{
 
    /*1 删除数据*/
    NSInteger index1 = -1;
    NSMutableIndexSet *shopSelectIndex = [NSMutableIndexSet indexSet];
    for (NSMutableArray *shopArray in self.cartData) {
        index1++;
        
        NSInteger index2 = -1;
        NSMutableIndexSet *selectIndexSet = [NSMutableIndexSet indexSet];
        for (JSCartModel *model in shopArray) {
            index2++;
            if (model.isSelect) {
                [selectIndexSet addIndex:index2];
            }
        }
        NSInteger shopCount = shopArray.count;
        NSInteger selectCount = selectIndexSet.count;
        if (selectCount == shopCount) {
            [shopSelectIndex addIndex:index1];
            self.cartGoodsCount-=selectCount;
        }
        [shopArray removeObjectsAtIndexes:selectIndexSet];
    }
    [self.cartData removeObjectsAtIndexes:shopSelectIndex];
    /*2 删除 shopSelectArray*/
    [self.shopSelectArray removeObjectsAtIndexes:shopSelectIndex];
    [self.cartTableView reloadData];
    /*3 carbar 恢复默认*/
    self.allPrices = 0;
    /*重新计算价格*/
    self.allPrices = [self getAllPrices];
}

VC做监听观察处理

全选

 [[self.cartBar.selectAllButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton *x) {
        x.selected = !x.selected;
        [self.viewModel selectAll:x.selected];
    }];

删除

[[self.cartBar.deleteButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton *x) {
    [self.viewModel deleteGoodsBySelect];
}];

结算

[[self.cartBar.balanceButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton *x) {
        
    }];

观察价格属性

WEAK
[RACObserve(self.viewModel, allPrices) subscribeNext:^(NSNumber *x) {
    STRONG
    self.cartBar.money = x.floatValue;
}];

全选状态

RAC(self.cartBar.selectAllButton,selected) = RACObserve(self.viewModel, 	isSelectAll);

title购物车数量

[RACObserve(self.viewModel, cartGoodsCount) subscribeNext:^(NSNumber *x) {
   STRONG
    if(x.integerValue == 0){
        self.title = [NSString stringWithFormat:@"购物车"];
    } else {
        self.title = [NSString stringWithFormat:@"购物车(%@)",x];
    }
    
}];

总结

主要的方法我都一一讲了很清楚,具体的怎么调用,可以到service里,cell里,控件里看,写了这么一大堆,如果你还有什么不懂,或者有更好的建议请留言,或者到我的github上issue我,如果我写的对你有些帮助,请给予辛劳的博主一些打赏,谢谢~

jsshopcartmodule's People

Contributors

jjosin22 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

jsshopcartmodule's Issues

购物车数量编辑的时候键盘遮挡问题

非常感谢作者的demo,使我受益匪浅,在原有demo的基础上我新加了一个自认为很不错的开源框架
pod 'IQKeyboardManager', '~> 4.0.3'用来解决键盘遮挡问题,pod安装后不需要一行代码便可以避免遮挡问题

不属于MVVM

  1. controller 中的tableview 为何要放到viewModel中
    2.JSCartCell引用了JSCartModel,不符合MVVM

刷新数据是闪动

你好,购物车通用模块,在后面的数据选中刷新时 界面跳动 有什么好的解决方法吗?麻烦指教,QQ365458744

单个商品删除时,商家选中状态未一起改变.

比如第一组组头我不选中,里面有1 2 3 4个商品,我选中 2 3 4,不选中1. 此时组头是不选中的,这没问题. 但是这时我把1删除了,此组只有2 3 4,均为选中,组头也应该变成选中状态,但是这没跟着变. 应该在删除单个cell的时候 对组头的选中状态进行遍历改变.

购物车分页

如果购物车分页加载数据,需要注意什么,请大佬指教。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.