商品选择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 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 *properties;

@property (nonatomic, strong, readonly) NSArray *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 *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

你可能感兴趣的:(商品选择SKUDataFilter)