Demo效果:
![](https://i-blog.csdnimg.cn/blog_migrate/7759506fa69adef48c69e26ad1b1e338.webp?x-image-process=image/format,png)
example.gif
工程结构图:
![](https://i-blog.csdnimg.cn/blog_migrate/70d536697d2f97dd97807f768755952e.webp?x-image-process=image/format,png)
结构图.png
1.模拟组装数据,因为可能是多层的,所以我们这里通过组合模式来组装数据。在MMBaseItem
里面我们定义了三个枚举:
//这个字段我们暂时留着以后扩展,覆盖可能要有些选项不能选择,显示灰色的情况
typedef NS_ENUM(NSUInteger, MMPopupViewMarkType) { //选中的状态
MMPopupViewDisplayTypeSelected = 0, //可以选中
MMPopupViewDisplayTypeUnselected = 1, //不可以选中
};
typedef NS_ENUM(NSUInteger, MMPopupViewSelectedType) { //是否支持单选或者多选
MMPopupViewSingleSelection, //单选
MMPopupViewMultilSeMultiSelection, //多选
};
typedef NS_ENUM(NSUInteger, MMPopupViewDisplayType) { //分辨弹出来的view类型
MMPopupViewDisplayTypeNormal = 0, //一层
MMPopupViewDisplayTypeMultilayer = 1, //两层
MMPopupViewDisplayTypeFilters = 2, //混合
};
MMItem
提供共同的接口,弹出视图由对应的MMItem
子类数据驱动。 由于MMPopupViewDisplayTypeNormal
和MMPopupViewDisplayTypeMultilayer
两种类型布局比较单一简单,所以layout
对象暂时只是在MMPopupViewDisplayTypeFilters
时有用。
当然我这里是模拟数据。下面给出一种建立树模型的思路:
![](https://i-blog.csdnimg.cn/blog_migrate/ad39d212381ada52a226c26848cf7642.webp?x-image-process=image/format,png)
屏幕快照 2016-12-22 下午11.14.13.png
1.1 首先我们把上图的根节点放到队列中
![](https://i-blog.csdnimg.cn/blog_migrate/d1a9143b16154714b1e330476be729f9.webp?x-image-process=image/format,png)
1.1.png
1.2 根据A持有子节点的指针把B,C放进队列,相当于把B,C添加到A的childrenNodes
。然后把A给移出队列。
![](https://i-blog.csdnimg.cn/blog_migrate/5cb0eaeea41467d640eef2abcd5e59ba.webp?x-image-process=image/format,png)
1.2
1.3 然后按照上面的逻辑一个一个的遍历每个节点。直到队列为空的时候代表一颗建立完毕。下面图未给全,只是部分状态的时刻图。
![](https://i-blog.csdnimg.cn/blog_migrate/852bb541fadf7380819ebc7dea145514.webp?x-image-process=image/format,png)
1.3.png
![](https://i-blog.csdnimg.cn/blog_migrate/ea1c5b553065357f4c42beabeb65dbea.webp?x-image-process=image/format,png)
1.4.png
![](https://i-blog.csdnimg.cn/blog_migrate/6f25d077cef0816689b5a0045d395a3a.webp?x-image-process=image/format,png)
1.5.png
2.初始化视图:
MMComBoBoxView *view = [[MMComBoBoxView alloc] initWithFrame:CGRectMake(0, 64, kScreenWidth, 40)];
view.dataSource = self;
view.delegate = self;
[self.view addSubview:view];
[view reload];
3.通过datasource协议将数据传给MMComBoBoxView
,你可以联想UITableView数据驱动方式就可以了。
#pragma mark - MMComBoBoxViewDataSource
- (NSUInteger)numberOfColumnsIncomBoBoxView :(MMComBoBoxView *)comBoBoxView {
return self.mutableArray.count;
}
- (MMItem *)comBoBoxView:(MMComBoBoxView *)comBoBoxView infomationForColumn:(NSUInteger)column {
return self.mutableArray[column];
}
4.我们会通过MMComBoBoxViewDelegate
协议把选中的路径回调出来,这里我们选择回调存储路径的数组的本质是在于可能开发人员上传的不止是title
,可能还有对应的code
等一系列的字段。这样方便扩展。
#pragma mark - MMComBoBoxViewDelegate
- (void)comBoBoxView:(MMComBoBoxView *)comBoBoxViewd didSelectedItemsPackagingInArray:(NSArray *)array atIndex:(NSUInteger)index {
MMItem *rootItem = self.mutableArray[index];
switch (rootItem.displayType) {
case MMPopupViewDisplayTypeNormal:
case MMPopupViewDisplayTypeMultilayer:{
//拼接选择项
NSMutableString *title = [NSMutableString string];
__block NSInteger firstPath;
[array enumerateObjectsUsingBlock:^(MMSelectedPath * path, NSUInteger idx, BOOL * _Nonnull stop) {
[title appendString:idx?[NSString stringWithFormat:@";%@",[rootItem findTitleBySelectedPath:path]]:[rootItem findTitleBySelectedPath:path]];
if (idx == 0) {
firstPath = path.firstPath;
}
}];
NSLog(@"当title为%@时,所选字段为 %@",rootItem.title ,title);
break;}
case MMPopupViewDisplayTypeFilters:{
MMCombinationItem * combineItem = (MMCombinationItem *)rootItem;
[array enumerateObjectsUsingBlock:^(NSMutableArray* _Nonnull subArray, NSUInteger idx, BOOL * _Nonnull stop) {
if (combineItem.isHasSwitch && idx == 0) {
for (MMSelectedPath *path in subArray) {
MMAlternativeItem *alternativeItem = combineItem.alternativeArray[path.firstPath];
NSLog(@"当title为: %@ 时,选中状态为: %d",alternativeItem.title,alternativeItem.isSelected);
}
return;
}
NSString *title;
NSMutableString *subtitles = [NSMutableString string];
for (MMSelectedPath *path in subArray) {
MMItem *firstItem = combineItem.childrenNodes[path.firstPath];
MMItem *secondItem = combineItem.childrenNodes[path.firstPath].childrenNodes[path.secondPath];
title = firstItem.title;
[subtitles appendString:[NSString stringWithFormat:@" %@",secondItem.title]];
}
NSLog(@"当title为%@时,所选字段为 %@",title,subtitles);
}];
break;}
default:
break;
}
}