商品选择SKUDataFilter

 *  github:https://github.com/SunriseOYR/SKUDataFilter

 *  bigo:https://www.jianshu.com/p/295737e2ac77

#import

#import

@class ORSKUDataFilter;

@class ORSKUProperty;

@protocolORSKUDataFilterDataSource

@required

//属性种类个数

- (NSInteger)numberOfSectionsForPropertiesInFilter:(ORSKUDataFilter*)filter;

/*

 * 每个种类所有的的属性值

 * 这里不关心具体的值,可以是属性ID, 属性名,字典、model

 */

- (NSArray*)filter:(ORSKUDataFilter*)filter propertiesInSection:(NSInteger)section;

//满足条件 的 个数

- (NSInteger)numberOfConditionsInFilter:(ORSKUDataFilter*)filter;

/*

 * 对应的条件式

 * 这里条件式的属性值,需要和propertiesInSection里面的数据类型保持一致

 */

- (NSArray*)filter:(ORSKUDataFilter*)filter conditionForRow:(NSInteger)row;

//条件式 对应的 结果数据(库存、价格等)

- (id)filter:(ORSKUDataFilter*)filter resultOfConditionForRow:(NSInteger)row;

@end

@interfaceORSKUDataFilter :NSObject

@property (nonatomic, assign) id<ORSKUDataFilterDataSource> dataSource;

//当前 选中的属性indexPath

@property(nonatomic,strong,readonly)NSArray *selectedIndexPaths;

//当前 可选的属性indexPath

@property(nonatomic,strong,readonly)NSSet *availableIndexPathsSet;

//当前 结果

@property (nonatomic, strong, readonly) id  currentResult;

//init

- (instancetype)initWithDataSource:(id)dataSource;

//选中 属性的时候 调用

- (void)didSelectedPropertyWithIndexPath:(NSIndexPath*)indexPath;

//重新加载数据

- (void)reloadData;

@end

@interfaceORSKUCondition :NSObject

@property (nonatomic, strong) NSArray<ORSKUProperty *> *properties;

@property (nonatomic, strong, readonly) NSArray<NSNumber *> *conditionIndexs;

@property (nonatomic, strong) id result;

@end

@interfaceORSKUProperty :NSObject

@property (nonatomic, copy, readonly) NSIndexPath * indexPath;

@property (nonatomic, copy, readonly) id value;

- (instancetype)initWithValue:(id)value indexPath:(NSIndexPath*)indexPath;

@end


#import "ORSKUDataFilter.h"

@interface ORSKUDataFilter()

@property (nonatomic, strong) NSSet <ORSKUCondition *> *conditions;

@property(nonatomic,strong)NSMutableArray *selectedIndexPaths;

@property(nonatomic,strong)NSMutableSet *availableIndexPathsSet;

//全可用的

@property(nonatomic,strong)NSSet *allAvailableIndexPaths;

@property (nonatomic, strong) id  currentResult;

@end

@implementationORSKUDataFilter

- (instancetype)initWithDataSource:(id)dataSource

{

    self= [superinit];

    if(self) {

        _dataSource= dataSource;

        _selectedIndexPaths = [NSMutableArray array];

        [self initPropertiesSkuListData];

    }

    return self;

}

- (instancetype)init

{

    self= [superinit];

    if(self) {

        _selectedIndexPaths = [NSMutableArray array];

    }

    return self;

}

- (void)reloadData {

    [_selectedIndexPaths removeAllObjects];

    [self initPropertiesSkuListData];

    [self updateCurrentResult];

}

#pragma mark -- public method

//选中某个属性

- (void)didSelectedPropertyWithIndexPath:(NSIndexPath*)indexPath {


    if (![_availableIndexPathsSet containsObject:indexPath]) {

        //不可选

        return;

    }


    if(indexPath.section> [_dataSourcenumberOfSectionsForPropertiesInFilter:self] || indexPath.item>= [[_dataSourcefilter:selfpropertiesInSection:indexPath.section]count]) {

        //越界

        NSLog(@"indexPath is out of range");

        return;

    }


    if([_selectedIndexPathscontainsObject:indexPath]) {

        //已被选

        [_selectedIndexPathsremoveObject:indexPath];


        [self updateAvailableIndexPaths];

        [self updateCurrentResult];

        return;

    }


    __blockNSIndexPath*lastIndexPath =nil;


    [_selectedIndexPathsenumerateObjectsUsingBlock:^(NSIndexPath*_Nonnullobj,NSUIntegeridx,BOOL*_Nonnullstop) {

        if(indexPath.section== obj.section) {

            lastIndexPath = obj;

        }

    }];


    if(!lastIndexPath) {

        //添加新属性

        [_selectedIndexPathsaddObject:indexPath];

        [_availableIndexPathsSet intersectSet:[self availableIndexPathsFromSelctedIndexPath:indexPath sectedIndexPaths:_selectedIndexPaths]];

        [self updateCurrentResult];

        return;

    }


    if(lastIndexPath.item!= indexPath.item) {

        //切换属性

        [_selectedIndexPathsaddObject:indexPath];

        [_selectedIndexPathsremoveObject:lastIndexPath];

        [self updateAvailableIndexPaths];

        [self updateCurrentResult];

    }


}

#pragma mark -- private method

//获取初始数据

- (void)initPropertiesSkuListData {


    NSMutableSet *modelSet = [NSMutableSet set];

    for(inti =0; i < [_dataSourcenumberOfConditionsInFilter:self]; i ++) {


        ORSKUCondition *model = [ORSKUCondition new];

        NSArray* conditions = [_dataSourcefilter:selfconditionForRow:i];


        if(![selfcheckConformToSkuConditions:conditions]) {

            NSLog(@"第 %d 个 condition 不完整 \n %@", i, conditions);

            continue;

        }


        model.properties= [selfpropertiesWithConditionRawData:conditions];

        model.result = [_dataSource filter:self resultOfConditionForRow:i];


        [modelSetaddObject:model];

    }

    _conditions= [modelSetcopy];


    [self getAllAvailableIndexPaths];

}

//检查数据是否正确

- (BOOL)checkConformToSkuConditions:(NSArray*)conditions {

    if (conditions.count != [_dataSource numberOfSectionsForPropertiesInFilter:self]) {

        returnNO;

    }


    __blockBOOL  flag =YES;

    [conditionsenumerateObjectsUsingBlock:^(id  _Nonnullobj,NSUIntegeridx,BOOL*_Nonnullstop) {

        NSArray*properties = [_dataSourcefilter:selfpropertiesInSection:idx];

        if(![propertiescontainsObject:obj]) {

            flag =NO;

            *stop =YES;

        }

    }];

    returnflag;

}

//获取属性

- (NSArray *)propertiesWithConditionRawData:(NSArray*)data {


    NSMutableArray *array = [NSMutableArray array];

    [dataenumerateObjectsUsingBlock:^(id  _Nonnullobj,NSUIntegeridx,BOOL*_Nonnullstop) {

        [arrayaddObject:[selfpropertyOfValue:objinSection:idx]];

    }];


    returnarray;

}

- (ORSKUProperty*)propertyOfValue:(id)value inSection:(NSInteger)section {


    NSArray*properties = [_dataSourcefilter:selfpropertiesInSection:section];


    NSString *str = [NSString stringWithFormat:@"Properties for %ld dosen‘t exist %@", (long)section, value];

    NSAssert([properties containsObject:value], str);


    NSIndexPath*indexPath = [NSIndexPathindexPathForItem:[propertiesindexOfObject:value]inSection:section];


    return[[ORSKUPropertyalloc]initWithValue:valueindexPath:indexPath];

}

//获取条件式 对应 的数据

- (id)skuResultWithConditionIndexs:(NSArray *)conditionIndexs {


    __blockidresult =nil;


    [_conditionsenumerateObjectsUsingBlock:^(ORSKUCondition*_Nonnullobj,BOOL*_Nonnullstop) {


        if([obj.conditionIndexsisEqual:conditionIndexs]) {

            result = obj.result;

            *stop =YES;

        }

    }];


    returnresult;

}

//获取初始可选的所有IndexPath

- (NSMutableSet *)getAllAvailableIndexPaths {

    NSMutableSet *set = [NSMutableSet set];

    [_conditionsenumerateObjectsUsingBlock:^(ORSKUCondition*_Nonnullobj,BOOL*_Nonnullstop) {

        [obj.conditionIndexsenumerateObjectsUsingBlock:^(NSNumber*_Nonnullobj1,NSUIntegeridx1,BOOL*_Nonnullstop1) {

            [setaddObject:[NSIndexPathindexPathForItem:obj1.integerValueinSection:idx1]];

        }];

    }];


    _availableIndexPathsSet = set;


    _allAvailableIndexPaths = [set copy];


    returnset;

}

//选中某个属性时 根据已选中的系列属性 获取可选的IndexPath

- (NSMutableSet *)availableIndexPathsFromSelctedIndexPath:(NSIndexPath*)selectedIndexPath sectedIndexPaths:(NSArray *)indexPaths{


    NSMutableSet *set = [NSMutableSet set];

    [_conditionsenumerateObjectsUsingBlock:^(ORSKUCondition*_Nonnullobj,BOOL*_Nonnullstop) {

        if([obj.conditionIndexsobjectAtIndex:selectedIndexPath.section].integerValue== selectedIndexPath.item) {


            [obj.propertiesenumerateObjectsUsingBlock:^(ORSKUProperty*_Nonnullproperty,NSUIntegeridx2,BOOL*_Nonnullstop1) {


                //从condition中添加种类不同的属性时,需要根据已选中的属性过滤

                //过滤方式为 condition要么包含已选中 要么和已选中属性是同级

                if(property.indexPath.section!= selectedIndexPath.section) {


                    __blockBOOLflag =YES;


                    [indexPathsenumerateObjectsUsingBlock:^(NSIndexPath*_Nonnullobj1,NSUIntegeridx,BOOL*_Nonnullstop) {


                        flag = (([obj.conditionIndexs[obj1.section]integerValue] == obj1.row) || (obj1.section== property.indexPath.section)) && flag;

                    }];


                    if(flag) {

                        [setaddObject:property.indexPath];

                    }


                }else{

                    [setaddObject:property.indexPath];

                }

            }];

        }

    }];


    //合并本行数据

    [_allAvailableIndexPathsenumerateObjectsUsingBlock:^(NSIndexPath*_Nonnullobj,BOOL*_Nonnullstop) {

        if(obj.section== selectedIndexPath.section) {

            [setaddObject:obj];

        }

    }];


    returnset;

}

//当前可用的

- (void)updateAvailableIndexPaths {


    if (_selectedIndexPaths.count == 0) {


        _availableIndexPathsSet = [_allAvailableIndexPaths mutableCopy];

        return;

    }


    __block NSMutableSet *set = [NSMutableSet set];


    NSMutableArray *seleted = [NSMutableArray array];


    [_selectedIndexPathsenumerateObjectsUsingBlock:^(NSIndexPath*_Nonnullobj,NSUIntegeridx,BOOL*_Nonnullstop) {


        [seletedaddObject:obj];


        NSMutableSet*tempSet =nil;


        tempSet = [self availableIndexPathsFromSelctedIndexPath:obj sectedIndexPaths:seleted];


        if(set.count==0) {

            set = [tempSetmutableCopy];

        }else{

            [setintersectSet:tempSet];

        }


    }];


    _availableIndexPathsSet = set;


}

// 当前结果

- (void)updateCurrentResult {


    if (_selectedIndexPaths.count != [_dataSource numberOfSectionsForPropertiesInFilter:self]) {

        _currentResult = nil;

        return;

    }

    NSMutableArray *conditions = [NSMutableArray array];


    for (int i = 0; i < [_dataSource numberOfSectionsForPropertiesInFilter:self]; i ++) {

        [_selectedIndexPathsenumerateObjectsUsingBlock:^(NSIndexPath*_Nonnullobj,NSUIntegeridx,BOOL*_Nonnullstop) {

            if(obj.section== i) {

                [conditionsaddObject:@(obj.row)];

            }

        }];


    }

    _currentResult = [self skuResultWithConditionIndexs:[conditions copy]];

}

- (BOOL)isAvailableWithPropertyIndexPath:(NSIndexPath*)indexPath {


    __blockBOOLisAvailable =NO;


    [_conditionsenumerateObjectsUsingBlock:^(ORSKUCondition*_Nonnullobj,BOOL*_Nonnullstop) {

        if([obj.conditionIndexsobjectAtIndex:indexPath.section].integerValue== indexPath.row) {

            isAvailable =YES;

            *stop =YES;

        }

    }];;


    returnisAvailable;

}

#pragma mark -- setter

- (void)setDataSource:(id)dataSource {

    _dataSource= dataSource;

    [self initPropertiesSkuListData];

}

@end

@implementation ORSKUCondition

- (void)setProperties:(NSArray *)properties {


    _properties= properties;

    NSMutableArray *array = [NSMutableArray array];

    [propertiesenumerateObjectsUsingBlock:^(ORSKUProperty*_Nonnullobj,NSUIntegeridx,BOOL*_Nonnullstop) {

        [arrayaddObject:@(obj.indexPath.item)];

    }];

    _conditionIndexs = [array copy];

}

@end

@implementation ORSKUProperty

- (instancetype)initWithValue:(id)value indexPath:(NSIndexPath*)indexPath

{

    self= [superinit];

    if(self) {

        _value= value;

        _indexPath= indexPath;

    }

    return self;

}

@end

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容