iOS无限分组

前言:很久没有更新了,这段时间确实比较忙,也没什么时间去研究一些技术,也很难想出来去研究些什么。iOS发展至今,已经有很多优秀的文档,包含各个方面,自己也经常感慨自己写的,没有别人写的详细,有逻辑。笔者之前很多文章都设置为隐私了,没有再公开,一部分是因为太次,一部分是因为都是些烂大街的东西。
iOS无限分组,也是和朋友交流的时候,碰到的一个需求,目前采用的时候js交互实现的,笔者最近想来,还是用原生的写写试试。
笔者的习惯,所有逻辑注解,都在注释里,大家认真看代码里的注释
废话不多说了,先看下效果图


iOS无限分组_第1张图片
123.gif

1,设计思路

iOS无限分组_第2张图片
屏幕快照 2018-03-15 10.39.06.png

1,笔者是对原始数据进行了处理,用一个字典,来存储所有节点数据。
父节点的id作为key,所有父节点相同的数据组合成数组,作为value
所有显示的数据都再重新筛到一个数组里,通过对showArr的处理,来处理数据的展开收起。
2,原始数据介绍
原始数据是一个数组,里面放的是字典,字典的主要key-value为
p_id父节点id
id自身id
live自身层级
看一下原始数据的大致结构,笔者这里只写了五级,各位开发者们,可以自己再加层级测试。

_orgeArr = @[@{@"p_id":@"0",@"id":@"1.0",@"live":@"1"},
             @{@"p_id":@"0",@"id":@"2.0",@"live":@"1"},
             @{@"p_id":@"0",@"id":@"3.0",@"live":@"1"},
             @{@"p_id":@"0",@"id":@"4.0",@"live":@"1"},
             @{@"p_id":@"1.0",@"id":@"1.1",@"live":@"2"},
             @{@"p_id":@"1.0",@"id":@"1.2",@"live":@"2"},
             @{@"p_id":@"2.0",@"id":@"2.1",@"live":@"2"},
             @{@"p_id":@"4.0",@"id":@"4.1",@"live":@"2"},
             @{@"p_id":@"1.1",@"id":@"1.1.1",@"live":@"3"},
             @{@"p_id":@"1.1",@"id":@"1.1.2",@"live":@"3"},
             @{@"p_id":@"1.1.1",@"id":@"1.1.1.1",@"live":@"4"},
             @{@"p_id":@"1.1.1.1",@"id":@"1.1.1.1.1",@"live":@"5"}];

一生二,二生三,三生万物,阿弥陀佛,各位测试吧。
3,适用场景,大致举例哈
3.1,列表类(比如城市选择)
3.2, 社区评论类(笔者猜想可以用,没有实际实践过)
3.3,自己想去吧 0.0哈哈

2,原始数据处理

 _orgeArr = @[@{@"p_id":@"0",@"id":@"1.0",@"live":@"1"},
             @{@"p_id":@"0",@"id":@"2.0",@"live":@"1"},
             @{@"p_id":@"0",@"id":@"3.0",@"live":@"1"},
             @{@"p_id":@"0",@"id":@"4.0",@"live":@"1"},
             @{@"p_id":@"1.0",@"id":@"1.1",@"live":@"2"},
             @{@"p_id":@"1.0",@"id":@"1.2",@"live":@"2"},
             @{@"p_id":@"2.0",@"id":@"2.1",@"live":@"2"},
             @{@"p_id":@"4.0",@"id":@"4.1",@"live":@"2"},
             @{@"p_id":@"1.1",@"id":@"1.1.1",@"live":@"3"},
             @{@"p_id":@"1.1",@"id":@"1.1.2",@"live":@"3"},
             @{@"p_id":@"1.1.1",@"id":@"1.1.1.1",@"live":@"4"},
             @{@"p_id":@"1.1.1.1",@"id":@"1.1.1.1.1",@"live":@"5"}];
_dataDic = [[NSMutableDictionary alloc] init];
_showArr = [[NSMutableArray alloc] init];
[_orgeArr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    NSString *p_id = obj[@"p_id"];
//        NSString *s_id = obj[@"id"];
    NSMutableArray *arr = [[NSMutableArray alloc] init];
    if (_dataDic[p_id]) {
        [arr addObjectsFromArray:_dataDic[p_id]];
    }
    [arr addObject:obj];
    _dataDic[p_id] = arr;
    if (p_id.integerValue == 0) {
        [_showArr addObject:obj];
    }
}];

3,展开收起状态处理

//判断cell上是否有展开收起按钮
- (void)isShowBtnWithCell:(ListTableViewCell *)cell{
NSInteger btnTag = cell.showBtn.tag;
NSDictionary *dic = _showArr[btnTag];
NSString *s_id = dic[@"id"];
NSArray *arr = _dataDic[s_id];
if (arr && arr.count>0) {
    cell.showBtn.hidden = NO;
    //如果有展开收起按钮,判断是展开还是收起
    if ([_showArr containsObject:arr.firstObject]) {
//            [cell.showBtn setTitle:@"收起" forState:UIControlStateNormal];
        [cell.showBtn setImage:[UIImage imageNamed:@"delet"] forState:UIControlStateNormal];
    }else{
//            [cell.showBtn setTitle:@"展开" forState:UIControlStateNormal];
        [cell.showBtn setImage:[UIImage imageNamed:@"add"] forState:UIControlStateNormal];
    }
}else{
    [cell.showBtn setImage:[UIImage imageNamed:@"add"] forState:UIControlStateNormal];
//        [cell.showBtn setTitle:@"展开" forState:UIControlStateNormal];
    cell.showBtn.hidden = YES;
}

}

4,展开时插入需要展开的数据

//展开收起按钮的点击方法
- (void)showBtnAction:(UIButton *)btn{
//只要此方法走了,就代表有展开收起按钮
NSInteger btnTag = btn.tag;
NSDictionary *dic = _showArr[btnTag];
NSString *s_id = dic[@"id"];
NSArray *arr = _dataDic[s_id];
if ([_showArr containsObject:arr.firstObject]) {
    //此时是展开状态,要全部删除次级数据,变为收起状态
    //id为次级数据的判断依据
    [self delegateShowDataWithDic:dic];
    
}else{
    //此时是收起状态
    for (int i = 0; i < arr.count; i ++) {
        NSDictionary *obj = arr[i];
        if (![_showArr containsObject:obj]) {
            [_showArr insertObject:obj atIndex:btnTag+i+1];
        }
        
    }
}
[_tableView reloadData];
}

5,收起时,删除所有已展开的数据

   //递归删除所有展开的数据
- (void)delegateShowDataWithDic:(NSDictionary *)dic{
//当前节点的id为子节点的p_id
NSString *s_id = dic[@"id"];
NSLog(@"--%@",s_id);
NSArray *arr = _dataDic[s_id];
if (arr == nil) {
    for (NSInteger j = _showArr.count-1; j >= 0; j --) {
        NSDictionary *delDic = _showArr[j];
        
        //如果子节点的p_id和当前节点的id相同,则表示子节点需要删除
        if ([delDic[@"p_id"] isEqualToString:s_id]) {
            [_showArr removeObject:delDic];
        }
    }
}
for (NSInteger i = arr.count-1; i >= 0 ; i --) {
  
    if ([_showArr containsObject:arr[i]]) {
        
        for (NSInteger j = _showArr.count-1; j >= 0; j --) {
            NSDictionary *delDic = _showArr[j];
            
            //如果子节点的p_id和当前节点的id相同,则表示子节点需要删除
            if ([delDic[@"p_id"] isEqualToString:s_id]) {
                [self delegateShowDataWithDic:delDic];
                [_showArr removeObjectAtIndex:j];
            }
        }
    }
}
/*此方法有bug,保留是为了参考
if ([_showArr containsObject:arr.firstObject]) {
    //说明还有次级数据,继续递归
    [self delegateShowDataWithDic:arr.firstObject];
    
    for (NSInteger i = _showArr.count-1; i >= 0; i --) {
        NSDictionary *delDic = _showArr[i];
        //如果子节点的p_id和当前节点的id相同,则表示子节点需要删除
        if ([delDic[@"p_id"] isEqualToString:s_id]) {
            [_showArr removeObject:delDic];
        }
    }
}
 */
}

代码不多,逻辑也不是很复杂,大家仔细想想也就想通了。

你可能感兴趣的:(iOS无限分组)