基于项目中用到的多sku 选择的问题,提几点参考意见
- 思路
- 示例代码
- github
思路
针对多sku 选择的问题,当选中某一个规格的时候,目的是需要匹配出所有包含当前此项的所有可能的sku,随后视图显示出来直到选择到具体的sku。比如规格中有 红色L码32,黄色m码30,蓝色L码32 三个规格。选中红色,在尺码一栏和大小一栏 只能有对应的“L码”和”32”显示,选择L码,颜色一栏中 “红色”和“蓝色”都可以点亮。如何实现这个目标呢,
- 分拆。将每一个具体的SKU 拆分出具体的组合,例如红色L码32,可以拆出的组合是红色,L码,32,红色L码,红色32,L码32,红色L码32。 得到一组所有的子规格合并组合
- 选择的时候,合并过滤。例 选择L码,红色,在大小栏中只有 32 可点击,但是在颜色一栏中,蓝色是处于可点击状态。当选中某一项的时候,需要在当前子规格栏 用其他选中的子规格依次拼接每一个查询是否存在相应的规格(这块需要额外理解一下)。比如需要用选中的L码和32 依次 拼接“红色”,”蓝色”去查询是否存在此sku。
注意事项
- 初始化的时候需要扫描一遍所有sku的库存,无库存不可用
- 通过sku 的 option项进行拼接的时候需要考虑,多option情况下值一致的问题(数据或sku设定可能导致一致),例如 大小 : 32, XL,尺码 : XL,M (这种情况下会导致选中状态下的bug)
- 数据排序
讲解比较抽象,可以参考code进行思考
源码参考
code以作者自身项目中的表结构为例讲解,具体请参考ChooseSkuDemo
分拆数据的过程中的源码处理,例如:
// 组合算法 从m中获取n个元素
- (NSArray *)valueFromTotal:(NSInteger)m
count:(NSInteger)n
{
// 首先初始化,将数组前n个元素置1,表示第一个组合为前n个数。
NSMutableArray *nArry = [[NSMutableArray alloc]init];
for (NSInteger i = 0; i<m; i++) {
[nArry addObject:@(i<n?1:0)];
}
if (m == n) {
return @[nArry];
}
NSMutableArray *resault = [[NSMutableArray alloc]init];
// 全排第一次
[resault addObject:[nArry copy]];
BOOL isend = false;
//然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为“01”组合
while (!isend) {
// 从后往前走--一遍循环结束
NSInteger leftTotal1 = 0; //左侧的1的数量
for (NSInteger i = 0; i < m-1; i++) {
if ([nArry[i] intValue] == 1 && [nArry[i+1] intValue] == 0) {
// 然后左侧的所有的1 移到最左侧
for (NSInteger j = 0; j<i; j++) {
nArry[j] = @(j<leftTotal1?1:0);
}
// 找到第一个 10组合 变成 01
[nArry exchangeObjectAtIndex:i withObjectAtIndex:i+1];
[resault addObject:[nArry copy]];
// 当第一个“1”移动到数组的m-n的位置,即n个“1”全部移动到最右端时,就得到了最后一个组合。
if ([nArry indexOfObject:@1] == m-n) {
isend = true;
}
break; //一次循环结束--可以重新执行了
}
// 左侧多少个1
if ([nArry[i] intValue] == 1) {
leftTotal1++;
}
}
}
return resault;
}
得到所有可能的option组合
- (NSArray *)arryCombineFromSource:(NSArray *)source
{
if (source.count == 0) return nil;
NSMutableArray *resault = [[NSMutableArray alloc]init];
for (NSInteger i = 1; i <= source.count; i++) {
// Cn1 从n中取m个元素 顺序列出来
NSArray *arry = [self valueFromTotal:source.count count:i];
// 按照1的位置取出相应的元素[[1,0],[1],[0,1]]
for (NSInteger j = 0; j<arry.count; j++) {
NSMutableArray *value = [[NSMutableArray alloc]init];
NSArray *arryj = arry[j];
for (NSInteger k = 0;k<[arryj count]; k++) {
if ([arry[j][k] intValue] == 1) {
[value addObject:source[k]];
}
}
[resault addObject:[value mutableCopy]];
}
}
return resault;
}
开始的时候所有sku的扫描部分
// 初始化得到结果集
- (void)initSkus
{
@autoreleasepool {
// 根据现有的sku 字段 去重新排列可能有的所有情况
NSDictionary *optionDict = [self getAllSkuOptionKeys];
NSArray *keys = [optionDict allKeys];
for (NSInteger i = 0; i<keys.count; i++) {
NSString *skuKey = keys[i];
// 内容
AMDSupplySkuModel *model = _allSkuOptionValues[skuKey];
AYEOptionQuantityModel *optionModel = [[AYEOptionQuantityModel alloc]init];
optionModel.optionValue = [model allOptionValue];
optionModel.quantity = model.quantity;
optionModel.quantity_setting = model.quantity_setting;
NSArray *skuKeysAttrs = [skuKey componentsSeparatedByString:@";"];
// 将商品规格属性排列(按ASII码排列)
skuKeysAttrs = [skuKeysAttrs sortedArrayUsingSelector:@selector(compare:)];
// 对每个SKU信息key属性值进行拆分组合
// 并把结果集放入到集合
NSArray *flagArry = [self arryCombineFromSource:skuKeysAttrs];
for (NSInteger i =0; i < flagArry.count; i++) {
NSArray *flag = flagArry[i];
[self addSkuResaultWithKey:flag model:optionModel];
}
}
// 处理相应的键值
self.allSkuCombineKeys = [_allSkuCombinateResault allKeys];
}
}
Github
源码地址: https://github.com/xie244135119/ChooseSkuDemo
希望可以帮助有需要的人,如果有疑问,也可以互相交流