iOS 商品庫(kù)存管理 SKU的選擇

Github地址

項(xiàng)目需求

簡(jiǎn)單說(shuō)一下我的需求:服務(wù)端給我傳了兩組數(shù)據(jù)叶堆,要求實(shí)現(xiàn)淘寶選擇商品規(guī)格的功能塔淤。


選擇對(duì)應(yīng)商品規(guī)格摘昌,加入購(gòu)物車(chē)
//這是所有sku的數(shù)組,spec_array為每一條sku所包含的所有規(guī)格
"sku_list": [{
            "id": "5dea1d944a723c535f9a9354",
            "modified_date": "2019-12-06 17:21:24",
            "corp_code": "C00000",
            "modifier_id": "5a7c2050ca2d3c7baf85efd7",
            "spec_array": [{
                "spec_id": "5d00cf245d48ca10241adca3",
                "spec_item_name": "1顆\/約0.6分",
                "name": "主石重量",
                "spec_item_id": "5d00cf245d48ca10241adca8"
            }, {
                "spec_id": "5d00cca55d48ca10241adca0",
                "spec_item_name": "鉆石",
                "name": "材質(zhì)",
                "spec_item_id": "5d00cca55d48ca10241adca2"
            }, {
                "spec_id": "5de620914a723c0d7a971aeb",
                "spec_item_name": "A1",
                "name": "尺碼",
                "spec_item_id": "5de620914a723c0d7a971aec"
            }],
            "last_stock": "15",
            "is_active": "Y",
            "created_date": "2019-12-06 17:21:24",
            "stock": 15,
            "market_price": 100,
            "price": 88,
            "product_id": "5ddf766f4a723c3cb8deffdb",
            "creator_id": "5a7c2050ca2d3c7baf85efd7"
        },
......
]
//既然sku_list中有所有規(guī)格列表了高蜂,那么還有一個(gè)spec_list就是所有可以選擇的規(guī)格的數(shù)組了, value_list為每一個(gè)規(guī)格的屬性數(shù)組
"spec_list": [{
        "spec_id": "5de620914a723c0d7a971aeb",
        "spec_name": "尺碼",
        "value_list": [{
            "spec_item_id": "5de620914a723c0d7a971aed",
            "spec_item_name": "A2"
        }, {
            "spec_item_id": "5de620914a723c0d7a971aec",
            "spec_item_name": "A1"
        }, {
            "spec_item_id": "5de620914a723c0d7a971aee",
            "spec_item_name": "A3"
        }]
    }, {
        "spec_id": "5d00cf245d48ca10241adca3",
        "spec_name": "主石重量",
        "value_list": [{
            "spec_item_id": "5d00cf245d48ca10241adca6",
            "spec_item_name": "1顆\/約4.9分"
        }, {
            "spec_item_id": "5d00cf245d48ca10241adca8",
            "spec_item_name": "1顆\/約0.6分"
        }]
    }, {
        "spec_id": "5d00cca55d48ca10241adca0",
        "spec_name": "材質(zhì)",
        "value_list": [{
            "spec_item_id": "5d00cca55d48ca10241adca2",
            "spec_item_name": "鉆石"
        }, {
            "spec_item_id": "5d00cca55d48ca10241adca1",
            "spec_item_name": "K金"
        }]
    }]

大佬OrangeAL的文章iOS-SKU商品規(guī)格組合算法詳解提供了一種解決思路

數(shù)據(jù)處理

首先將數(shù)據(jù)整理成有效數(shù)據(jù)聪黎,將有效sku保存成一個(gè)按spec_list的順序排列的數(shù)組_skuData

_skuData = [[NSMutableArray alloc]init];
    NSArray *spec_list = _productModel.spec_list;
    if (spec_list) {
        for (int i = 0; i<_productModel.skuList.count; i++) {
            NSMutableDictionary *skuObj = [[NSMutableDictionary alloc]init];
            NSDictionary *skuItem = _productModel.skuList[i];
            [skuObj setValue:skuItem[@"id"] forKey:@"sku_id"];
            NSMutableArray *specItems = [[NSMutableArray alloc]init];
            NSDictionary *spec_array = skuItem[@"spec_array"];
            for (NSDictionary *item in spec_array) {
                [specItems addObject:item[@"spec_item_id"]];
            }
            NSMutableArray *tempArray = [[NSMutableArray alloc]init];
            for (int j = 0; j < spec_list.count; j++) {
                NSArray *value_list = spec_list[j][@"value_list"];
                [value_list enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                    if ([specItems containsObject:obj[@"spec_item_id"]]) {
                        [tempArray addObject:obj[@"spec_item_id"]];
                    }
                }];
            }
            NSString *spec_item_id_list = [tempArray componentsJoinedByString:@","];
            [skuObj setValue:spec_item_id_list forKey:@"spec_item_id_list"];
            [skuObj setValue:skuItem[@"stock"] forKey:@"store"];
            [skuObj setValue:skuItem[@"price"] forKey:@"price"];
            [_skuData addObject:skuObj];
        }
    }
_skuData的值為
[{
    price = 88;//價(jià)格
    "sku_id" = 5dea1d944a723c535f9a9354;
    "spec_item_id_list" = "5de620914a723c0d7a971aec,5d00cf245d48ca10241adca8,5d00cca55d48ca10241adca2";//當(dāng)前sku所包含的規(guī)格(按spec_list中規(guī)格順序排序,[尺碼id,主石重量id,材質(zhì)id])
    store = 15;//庫(kù)存
},
{
    price = 88;
    "sku_id" = 5dea1d944a723c535f9a9355;
    "spec_item_id_list" = "5de620914a723c0d7a971aee,5d00cf245d48ca10241adca8,5d00cca55d48ca10241adca2";
    store = 15;
},
{
    price = 88;
    "sku_id" = 5dea1d944a723c535f9a9356;
    "spec_item_id_list" = "5de620914a723c0d7a971aed,5d00cf245d48ca10241adca6,5d00cca55d48ca10241adca1";
    store = 15;
},
{
    price = 88;
    "sku_id" = 5dea1d944a723c535f9a9357;
    "spec_item_id_list" = "5de620914a723c0d7a971aee,5d00cf245d48ca10241adca6,5d00cca55d48ca10241adca1";
    store = 15;
}]

自定義collectionView

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@class ItemView;

/// 視圖的協(xié)議
@protocol ItemViewDelegate <NSObject>

@optional
-(void)didSelected:(ItemView *)itemView;

@end

/// 格子
@interface ItemView : UIView
/// 按鈕事件代理
@property (nonatomic, weak) id<ItemViewDelegate> delegate;
/// 是否是多行
@property (nonatomic, assign) BOOL isMultiLines;
/// 位置
@property (nonatomic, strong) NSIndexPath *indexPath;
/// 設(shè)置選中狀態(tài)
@property (nonatomic, assign) BOOL itemSelected;
/// 設(shè)置不可選
@property (nonatomic, assign) BOOL itemDisable;
/// 設(shè)置 文本框的文字 文字的最小寬度 最大寬度 文字的字體
- (void)setText:(NSString *)text minWith:(CGFloat)minWith maxWith:(CGFloat)maxWith font:(UIFont *)font;

@end

NS_ASSUME_NONNULL_END
#import "ItemView.h"

@interface ItemView ()

/// 文本框
@property (nonatomic, strong) UILabel *label;
/// 裝載內(nèi)容
@property (nonatomic, strong) UIView *contentView;
/// 最小寬度
@property (nonatomic, assign) CGFloat minWidth;
/// 選中的標(biāo)題顏色  邊框色
@property (nonatomic, strong) UIColor *selectedTitleColro;
/// 選中背景色
@property (nonatomic, strong) UIColor *selectedBgColor;
/// 未選中背景色
@property (nonatomic, strong) UIColor *unSelectedBgColor;
/// 未選中的標(biāo)題顏色
@property (nonatomic, strong) UIColor *unSelectedTitleColor;
/// 不可點(diǎn)擊的標(biāo)題顏色
@property (nonatomic, strong) UIColor *disableTitleColor;
/// 點(diǎn)擊事件(手勢(shì))
@property (nonatomic, strong) UITapGestureRecognizer *g;

@end

@implementation ItemView

- (instancetype)init {
    
    self = [super init];
    if (self) {
        
        _disableTitleColor = TextFColor;
        _selectedBgColor = ColorB;
        _unSelectedBgColor = ColorG2;
        _unSelectedTitleColor = TitleBColor;
        _selectedTitleColro = ButtonBColor;
        _minWidth = 70;
        
        _contentView = [[UIView alloc] init];
        _contentView.userInteractionEnabled = NO;
        _contentView.layer.cornerRadius = 4;
        _contentView.frameHeight = 28;
        [self addSubview:_contentView];
        
        _label = [[UILabel alloc] init];
        _label.textAlignment = NSTextAlignmentCenter;
        _label.userInteractionEnabled = NO;
        _label.font = ButtonBFont;
        _label.numberOfLines = 0;
        [self addSubview:_label];
        
        _isMultiLines = NO;

        _g = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(click)];
        _g.numberOfTapsRequired = 1;
        [self addGestureRecognizer:_g];
    }
    return self;
}

- (void)click{
    if (self.delegate && [self.delegate respondsToSelector:@selector(didSelected:)]) {
        [self.delegate didSelected:self];
    }
}

/// 設(shè)置 文本框的文字 文字的最小寬度 文字的字體
- (void)setText:(NSString *)text minWith:(CGFloat)minWith maxWith:(CGFloat)maxWith font:(UIFont *)font {
    CGFloat offset = 10;
    
    NSDictionary *dic = @{NSFontAttributeName: font};
    
    CGFloat maxW = [UIScreen mainScreen].bounds.size.width - offset * 2;
    
    CGSize stringSize = [text boundingRectWithSize:CGSizeMake(maxW, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil].size;
    
    CGFloat singleLineWidth = [text sizeWithAttributes:dic].width;  //計(jì)算單行字符串長(zhǎng)度
    CGFloat height = stringSize.height + offset;
    if (height < 28) {
        height = 28;
    }
    if (singleLineWidth > maxW) { //判斷是否多行
        stringSize.width = maxW;
        self.isMultiLines = YES;
    } else if (stringSize.width < minWith) {  //判斷是否小于最小寬度
        stringSize.width = minWith;
    }

    self.label.frame = CGRectMake(offset, offset*0.5, stringSize.width, height);
    self.contentView.frame = CGRectMake(offset * 0.5, offset * 0.5, stringSize.width + offset, height);
    self.frame = CGRectMake(0, 0, self.label.frame.size.width + offset * 2, self.label.frame.size.height + offset * 2);
    self.label.text = text;
    self.label.font = font;
}

- (void)setItemSelected:(BOOL)itemSelected {
    _itemSelected = itemSelected;
    if (_itemSelected) {
        [self.g setEnabled:YES];
        self.contentView.layer.borderWidth = 0;
        self.contentView.layer.borderColor = self.selectedTitleColro.CGColor;
        self.contentView.backgroundColor = self.selectedBgColor;
        self.label.textColor = self.selectedTitleColro;
    } else {
        [self.g setEnabled:YES];
        self.contentView.layer.borderWidth = 0;
        self.contentView.backgroundColor = self.unSelectedBgColor;
        self.label.textColor = self.unSelectedTitleColor;
    }
}

- (void)setItemDisable:(BOOL)itemDisable {
    _itemDisable = itemDisable;
    if (_itemDisable) {
        [self.g setEnabled:NO];
        self.contentView.layer.borderWidth = 0;
        self.contentView.backgroundColor = self.unSelectedBgColor;
        self.label.textColor = self.disableTitleColor;
    }
}
#import <UIKit/UIKit.h>
#import "ItemView.h"

NS_ASSUME_NONNULL_BEGIN

@class ItemCollectionView;

/// 視圖的協(xié)議
@protocol ItemViewDataSource <NSObject>
@required
/// 每一個(gè)格子是什么
- (ItemView *)itemCollectionView:(ItemCollectionView *)itemCollectionView cellForRowAtIndexPath:(NSIndexPath *)indexpath;
/// 每一行有多少個(gè)格子
- (NSInteger)itemCollectionView:(ItemCollectionView *)itemCollectionView numberOfRowsInSection:(NSInteger)section;
@optional
/// 一共有多少行
- (NSInteger)numberOfSectionsAt:(ItemCollectionView *)itemCollectionView;
/// 設(shè)置每一行的頭視圖
- (UIView *)itemCollectionView:(ItemCollectionView *)itemCollectionView headerInSection:(NSInteger)section;
/// 點(diǎn)擊事件
- (void)itemCollectionView:(ItemCollectionView *)itemCollectionView didSelectedIndexPath:(NSIndexPath *)indexpath;
@end

/// 裝載所有的小格子
@interface ItemCollectionView : UIScrollView
/// 數(shù)據(jù)代理
@property (nonatomic, weak) id<ItemViewDataSource> dataSource;
/// 重新創(chuàng)作視圖
- (void)createCollectionView;

@end

NS_ASSUME_NONNULL_END
#import "ItemCollectionView.h"

@interface ItemCollectionView () <ItemViewDelegate>

/// 內(nèi)容視圖
@property (nonatomic, strong) UIView *contentView;
/// 每一行有多少個(gè) 默認(rèn) 0 個(gè)
@property (nonatomic, assign) CGFloat rowCountOfSection;
/// 一共有多少行 默認(rèn)1行
@property (nonatomic, assign) CGFloat sectionCount;
/// 臨時(shí)數(shù)組
@property (nonatomic, strong) NSMutableArray *viewsArray;
/// 內(nèi)部控件集合
@property (nonatomic, strong) NSArray *itemViewArray;

@end

@implementation ItemCollectionView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setUp];
    }
    return self;
}

- (void)awakeFromNib {
    [super awakeFromNib];
    [self setUp];
}

- (void)setUp {
    _rowCountOfSection = 0;
    _sectionCount = 1;
    _viewsArray = [NSMutableArray array];
}

- (void)initView {
    
    if (self.contentView != nil) {
        [self.contentView removeFromSuperview];
    }
    self.contentView = [[UIView alloc] init];
    [self addSubview:self.contentView];
    
    /// 有多少行, 可選代理
    if (self.dataSource && [self.dataSource respondsToSelector:@selector(numberOfSectionsAt:)]) {
        self.sectionCount = [self.dataSource numberOfSectionsAt:self];
    }
    
    /// 每一行有多少個(gè)格子,必選
    if (self.dataSource) {
        BOOL a = [self.dataSource respondsToSelector:@selector(itemCollectionView:numberOfRowsInSection:)];
        BOOL b = [self.dataSource respondsToSelector:@selector(itemCollectionView:cellForRowAtIndexPath:)];
        NSAssert((a && b), @"代理對(duì)象沒(méi)有遵守協(xié)議!");
    } else {
        NSAssert(NO, @"代理對(duì)象為空!");
    }
    
    CGFloat allSectionHeight = 0;
    for (NSInteger i = 0; i < self.sectionCount; i++) {
        UIView *sectionView = [[UIView alloc] init];
        UIView *headView = [self.dataSource itemCollectionView:self headerInSection:i];
        headView.frame = CGRectMake(headView.frame.origin.x, 0, self.bounds.size.width, headView.frame.size.height);
        [sectionView addSubview:headView];
        CGFloat offsetY = headView.frame.size.height;
        UIView *lastrowCell;
        
        self.rowCountOfSection = [self.dataSource itemCollectionView:self numberOfRowsInSection:i];
        
        NSMutableArray *array = [NSMutableArray array];
        
        ItemView *lastCell = nil; //最后一個(gè)單元
        
        for (NSInteger k = 0; k < self.rowCountOfSection; k++) {
            NSIndexPath *index = [NSIndexPath indexPathForRow:k inSection:i];
            ItemView *rowCell = [self.dataSource itemCollectionView:self cellForRowAtIndexPath: index];
            rowCell.delegate = self;
            rowCell.indexPath = index;
            
            
            if (lastCell) {  //最后一個(gè)單元存在
                
                if (CGRectGetMaxX(lastCell.frame) + rowCell.frame.size.width > self.bounds.size.width) { //新來(lái)的這個(gè)在后面放不下
                    
                    offsetY += lastCell.frame.size.height;  //放不下就放到下一行
                    
                    rowCell.frame = CGRectMake(0, offsetY, rowCell.frame.size.width, rowCell.frame.size.height);
                    
                } else {
                    
                    if (lastCell.isMultiLines) { //上一個(gè)是多行, 當(dāng)前就另起一行
                        offsetY += lastCell.frame.size.height;
                    }
                    
                    rowCell.frame = CGRectMake(CGRectGetMaxX(lastCell.frame), offsetY, rowCell.frame.size.width, rowCell.frame.size.height);
                }
                
            } else { //最后一個(gè)單元不存在
                
                rowCell.frame = CGRectMake(0, offsetY, rowCell.frame.size.width, rowCell.frame.size.height);
            }
            
            lastCell = rowCell;

            
            [sectionView addSubview:rowCell];
            lastrowCell = rowCell;
            [array addObject:rowCell];
        }
        CGFloat sectionHeight = CGRectGetMaxY(lastrowCell.frame) + 5; // +5是為了底部多留點(diǎn)空白
        sectionView.frame = CGRectMake(0, allSectionHeight, self.bounds.size.width, sectionHeight);
        [self.contentView addSubview:sectionView];
        allSectionHeight += sectionHeight;
                
        [self.viewsArray addObject:array];
    }
    self.contentView.frame = CGRectMake(0, 0, self.bounds.size.width, allSectionHeight);
    if (allSectionHeight < self.frameHeight) {
        self.contentSize = CGSizeMake(0, self.frameHeight+1);
    }
    else {
        self.contentSize = self.contentView.frame.size;
    }
    self.itemViewArray = self.viewsArray;
}


#pragma mark - ItemViewDelegate
- (void)didSelected:(ItemView *)itemView {
    
    for (ItemView *v in self.itemViewArray[itemView.indexPath.section]) {
        if (v.itemDisable) { continue; }
        v.itemSelected = NO;
    }
    itemView.itemSelected = YES;
    
    if (_dataSource && [self.dataSource respondsToSelector:@selector(itemCollectionView:didSelectedIndexPath:)]) {
        [self.dataSource itemCollectionView:self didSelectedIndexPath:itemView.indexPath];
    }
}

- (void)createCollectionView {
    [self setNeedsLayout];
    [self layoutIfNeeded];
    [self initView];
}


@end
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface ChooseSpecModel : NSObject

/// 名稱(chēng)
@property (strong,nonatomic) NSString *spec_name;
/// id
@property (strong,nonatomic) NSString *spec_id;
/// 詳情列表
@property (strong,nonatomic) NSMutableArray *itemArray;

@end

typedef NS_ENUM(NSInteger, ItemType) {  // 0 是默認(rèn)值, 不能設(shè)置為 0
    ItemDisable = 4,       //不可選
    ItemForceSelected = 1, //強(qiáng)制選中
    ItemSelected = 2,      //選中
    ItemUnSelected = 3     //未選中
};

@interface SpecItemModel : NSObject
/// 名稱(chēng)
@property (strong,nonatomic) NSString *spec_item_id;
/// id
@property (strong,nonatomic) NSString *spec_item_name;
/// 自定義屬性 標(biāo)記選項(xiàng)狀態(tài)
@property (assign,nonatomic) ItemType itemType;

@end
#import "ChooseSpecModel.h"

@implementation ChooseSpecModel

- (instancetype)init {
    if (self = [super init]) {
        _itemArray = [NSMutableArray array];
    }
    return self;
}

- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
    
}

@end


@implementation SpecItemModel

@end
創(chuàng)建collectionView备恤,需導(dǎo)入ORSKUDataFiltergit地址SKUDataFilter.
/// 商品選擇視圖
@property (nonatomic, strong) ItemCollectionView *itemCollectionView;
/// 數(shù)據(jù)
@property (strong, nonatomic) NSMutableArray *dataSource;
//ORSKUDataFilter
@property (nonatomic, strong) ORSKUDataFilter *filter;

- (void)drawSpecView {
    self.itemCollectionView = [[ItemCollectionView alloc] initWithFrame:CGRectMake(20, 100, KScreenWidth-40, 300)];
    self.itemCollectionView.dataSource = self;
    [showView addSubview:self.itemCollectionView];
    _selectedIndexPaths = [NSMutableArray array];
    NSArray *spec_list = _productModel.spec_list;
    self.dataSource = [NSMutableArray array];
    for (NSDictionary *dic in spec_list) {
        ChooseSpecModel *info = [[ChooseSpecModel alloc] init];
        [info setValuesForKeysWithDictionary:dic];
        for (NSDictionary *subDic in dic[@"value_list"]) {
            SpecItemModel *item = [[SpecItemModel alloc] init];
            [item setValuesForKeysWithDictionary:subDic];
            item.itemType = ItemUnSelected;
            [info.itemArray addObject:item];
        }
        [self.dataSource addObject:info];
    }
    _filter = [[ORSKUDataFilter alloc] initWithDataSource:self];

    // 加載視圖
    [self.itemCollectionView createCollectionView];
}

#pragma mark -- ORSKUDataFilterDataSource

- (NSInteger)numberOfSectionsForPropertiesInFilter:(ORSKUDataFilter *)filter {
    return self.dataSource.count;
}

- (NSArray *)filter:(ORSKUDataFilter *)filter propertiesInSection:(NSInteger)section {
    ChooseSpecModel *specModel = (ChooseSpecModel *)self.dataSource[section];
    NSMutableArray *temArr = [[NSMutableArray alloc]init];
    [specModel.itemArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        SpecItemModel *item = (SpecItemModel *)obj;
        [temArr addObject:item.spec_item_id];
    }];
    return temArr;
}

- (NSInteger)numberOfConditionsInFilter:(ORSKUDataFilter *)filter {
    return _skuData.count;
}

- (NSArray *)filter:(ORSKUDataFilter *)filter conditionForRow:(NSInteger)row {
    NSString *condition = _skuData[row][@"spec_item_id_list"];
    return [condition componentsSeparatedByString:@","];
}

- (id)filter:(ORSKUDataFilter *)filter resultOfConditionForRow:(NSInteger)row {
    NSDictionary *dic = _skuData[row];
    return @{@"price"   : dic[@"price"],
             @"store"   : dic[@"store"],
             @"sku_id"  : dic[@"sku_id"]};
}

#pragma mark - ItemViewDataSource 代理
- (NSInteger)numberOfSectionsAt:(ItemCollectionView *)itemCollectionView {
    return self.dataSource.count;
}

- (NSInteger)itemCollectionView:(ItemCollectionView *)itemCollectionView numberOfRowsInSection:(NSInteger)section {
    ChooseSpecModel *info = self.dataSource[section];
    return info.itemArray.count;
}

- (ItemView *)itemCollectionView:(ItemCollectionView *)itemCollectionView cellForRowAtIndexPath:(NSIndexPath *)indexpath {
    ChooseSpecModel *info = self.dataSource[indexpath.section];
    SpecItemModel *item = info.itemArray[indexpath.row];
    ItemView *v = [[ItemView alloc] init];
    [v setText:item.spec_item_name minWith:70 maxWith:showView.frameWidth-40 font:TitleBFont];
    
    if ([_filter.availableIndexPathsSet containsObject:indexpath]) {
        v.itemSelected = NO;
    }else {
        v.itemDisable = YES;
    }
    
    if ([_filter.selectedIndexPaths containsObject:indexpath]) {
        v.itemSelected = YES;
    }

    return v;
}

- (UIView *)itemCollectionView:(ItemCollectionView *)itemCollectionView headerInSection:(NSInteger)section {
    ChooseSpecModel *info = self.dataSource[section];
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(15, 0, 0, 40)];
    label.text = info.spec_name;
    label.font = TitleBFont;
    label.textColor = TitleBColor;
    return label;
}

- (void)itemCollectionView:(ItemCollectionView *)itemCollectionView didSelectedIndexPath:(NSIndexPath *)indexpath {
    [_filter didSelectedPropertyWithIndexPath:indexpath];
    [_itemCollectionView createCollectionView];

    NSSet *selectedIndexPaths = _filter.selectedIndexPaths;
    // 查看結(jié)果
    NSMutableString *tempresult = [NSMutableString string];
    [selectedIndexPaths enumerateObjectsUsingBlock:^(id  _Nonnull obj, BOOL * _Nonnull stop) {
        NSIndexPath *indexPath = (NSIndexPath *)obj;
        ChooseSpecModel *infoR = self.dataSource[indexPath.section];
        SpecItemModel *itemR = infoR.itemArray[indexPath.row];
        if (tempresult.length > 0) {
            [tempresult appendFormat:@","];
        }
        [tempresult appendFormat:@"%@", itemR.spec_item_name];
    }];
    
}

以上為全部實(shí)現(xiàn)代碼稿饰,具體理解如下

[indexPath(0,0),indexPath(0,1),indexPath(0,2),
indexPath(1,0),indexPath(1,1),
indexPath(2,0),indexPath(2,1)]
每一個(gè)規(guī)格所在的indexPath

每一條sku都有按照section的順序都可以根據(jù)indexPath.row生成一個(gè)所在位置的數(shù)組锦秒,例如SKU A2+1顆/約4.9分+K金 可以寫(xiě)成[0,0,1],那么四種組合方式可以得到四個(gè)數(shù)組
valid_paths = [[0,0,1],[2,0,1],[1,1,0],[2,1,0]]

根據(jù)有效的sku獲取到所有可以點(diǎn)擊的item數(shù)組

NSMutableSet *set = [NSMutableSet set];//set為所有可點(diǎn)擊的item的indexPath的集合
[valid_paths enumerateObjectsUsingBlock:^(id *_Nonnull obj, BOOL * _Nonnull stop) {
        [obj enumerateObjectsUsingBlock:^(NSNumber * _Nonnull obj1, NSUInteger idx, BOOL * _Nonnull stop1) {
            [set addObject:[NSIndexPath indexPathForItem:obj inSection:idx]];
        }];
 }];

當(dāng)?shù)谝淮吸c(diǎn)擊了K金所在的item喉镰,selectedIndexPath的值為(2,1),遍歷valid_paths數(shù)組旅择,獲取可點(diǎn)擊indexPath的數(shù)組,再將當(dāng)前可點(diǎn)擊數(shù)組與之前所有可點(diǎn)擊item數(shù)組取交集侣姆,就是當(dāng)前可以點(diǎn)擊的按鈕生真。

[valid_paths enumerateObjectsUsingBlock:^(id *_Nonnull obj, BOOL * _Nonnull stop) {
       //假設(shè)obj為[2,1,0]時(shí),即有效sku為A3+1顆/約0.6分+鉆石時(shí)铺敌,選中的item為該sku中的一項(xiàng)規(guī)格汇歹。
      
//此時(shí)obj中的[2,1偿凭,0]轉(zhuǎn)換成indexPath的數(shù)組時(shí)产弹,應(yīng)該是paths = [(0,2),(1,1),(2,0)],遍歷paths
if(obj[selectedIndexPath.section] == selectedIndexPath.row){
 [paths enumerateObjectsUsingBlock:^(NSindexPath * _Nonnull indexPath, NSUInteger idx, BOOL * _Nonnull stop1) {
            if(selectedIndexPath.section == indexPath.section) {
                //兄弟item都為可選擇
             }
            else {
              //如果其他section中indexPath.row == selectedIndexPath.row,則也為可選擇
            }
        }];
    }
}
   
}];

刷新數(shù)據(jù),頁(yè)面就顯示初當(dāng)前選擇的item和其他可選擇的數(shù)據(jù)item弯囊,不可選擇的則置灰

已經(jīng)選中了某個(gè)item痰哨,點(diǎn)擊第二個(gè)item時(shí)則和上面方法一樣,此時(shí)會(huì)得到一個(gè)新的可以選擇的item的集合匾嘱,將第二次的集合與第一次的集合取交集則得到一個(gè)新的可以選擇的item的集合

總結(jié)

我在一開(kāi)始陷入了一個(gè)死循環(huán)斤斧,幸虧及時(shí)看到了大佬OrangeAL的文章iOS-SKU商品規(guī)格組合算法詳解的文章,git地址SKUDataFilter.
在此感謝霎烙!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末撬讽,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子悬垃,更是在濱河造成了極大的恐慌游昼,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尝蠕,死亡現(xiàn)場(chǎng)離奇詭異烘豌,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)看彼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)廊佩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人靖榕,你說(shuō)我怎么就攤上這事标锄。” “怎么了序矩?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵鸯绿,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng)瓶蝴,這世上最難降的妖魔是什么毒返? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮舷手,結(jié)果婚禮上拧簸,老公的妹妹穿的比我還像新娘。我一直安慰自己男窟,他們只是感情好盆赤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著歉眷,像睡著了一般牺六。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上汗捡,一...
    開(kāi)封第一講書(shū)人閱讀 51,604評(píng)論 1 305
  • 那天淑际,我揣著相機(jī)與錄音,去河邊找鬼扇住。 笑死春缕,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的艘蹋。 我是一名探鬼主播锄贼,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼女阀!你這毒婦竟也來(lái)了宅荤?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤浸策,失蹤者是張志新(化名)和其女友劉穎膘侮,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體的榛,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年逻锐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了夫晌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡昧诱,死狀恐怖晓淀,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情盏档,我是刑警寧澤凶掰,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響懦窘,放射性物質(zhì)發(fā)生泄漏前翎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一畅涂、第九天 我趴在偏房一處隱蔽的房頂上張望港华。 院中可真熱鬧,春花似錦午衰、人聲如沸立宜。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)橙数。三九已至,卻和暖如春帅戒,著一層夾襖步出監(jiān)牢的瞬間灯帮,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工蜘澜, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留施流,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓鄙信,卻偏偏與公主長(zhǎng)得像瞪醋,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子装诡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355