26
2017
09

NSSortDescriptor和NSPredicate的使用总结

在这个项目中遇到了一些对数组、字典进行的复杂操作的需求,具体表现在播放历史那一块,需求如下:

要本地用sqlite存储播放过的视频vid和视频播放的时间戳sort_time,然后再用数组转字符串的形式给接口传这些vid,用来获取视频详情信息。把从接口获取到的json数据转成模型数组dataArray之后,数组里的数据可能是无序的,所以要先对数组进行按时间戳降序排列,排序完了之后还要对这些数据进行按日期进行分组重新组合,同一日期的数据放在一组,然后把重新组合过的数据存入historyArray数组,同时要保证historyArray数组里的每组数据都是按照日期降序排列好的,然后再进行使用。

           差不多类似于下面的这个形式

原始数据:

这里写图片描述

按需求整理之后的数据:

这里写图片描述

通过代码来说一下我的处理方式:

//接口获取到的数据存入dataArray,然后给dataArray插入sort_time时间戳
        [self.dataArray enumerateObjectsUsingBlock:^(STPlayHistoryModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            STPlayHistoryModel *info = obj;
            [_tableArray enumerateObjectsUsingBlock:^(NSDictionary *_Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                if ((info.vid == [obj[@"vid"] integerValue])) {

                    info.sort_time = [obj[@"time"] doubleValue];
                }
            }];
        }];
        //如果服务器不按照我传入的Vid的顺序进行返回数据,那么就给dataArray插入sort_time时间戳,按时间戳的顺序给数组排序,然后再把时间戳转换为play_time字符串

        // 对self.dataArray按sort_time的顺序进行降序排列 YES升序、NO降序
        NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"sort_time" ascending: NO];
        [self.dataArray sortUsingDescriptors:@[sortDescriptor]];

        //键值倒转,提取play_time
        NSMutableDictionary *dateDictionary = [NSMutableDictionary dictionaryWithCapacity:5];
        for (int i = 0; i< self.dataArray.count ; i++){
            [dateDictionary setValue:@"" forKey:[NSString stringWithFormat:@"%@",self.dataArray[i].play_time]];
        }

        //play_time在dateDictionary字典里作为key进行存储有可能是无序的,所以给dateDictionary按key进行排序
        NSMutableArray *keyArray = [[NSMutableArray alloc] init];
        for (int k = 0 ; k < [dateDictionary allKeys].count; k++) {
            [keyArray addObject:[dateDictionary allKeys][k]];
        }

        //对keyArray里进行降序排列
        NSSortDescriptor *keySortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:NO];
        [keyArray sortUsingDescriptors:@[keySortDescriptor]];

        //同一个日期的数据放一组,谓词筛选后存入self.historyArray进行使用
        _historyArray = [[NSMutableArray alloc] init];
        for (int j = 0; j< keyArray.count; j++){
            NSString *condition = [NSString stringWithFormat:@"SELF.play_time = '%@'",keyArray[j]];
            NSPredicate *predicate = [NSPredicate predicateWithFormat:condition];
            [_historyArray addObject:[self.dataArray filteredArrayUsingPredicate:predicate]];
        }

这里面有一些我也是首次使用的API,做一下说明和介绍:
1. NSSortDescriptor 是一个给数组排序的API,按照某一个条件进行排序,,比如这里就按照数组里sort_time的值的大小进行排序,YES表示升序,NO表示降序; sortUsingDescriptors是把一个指定的NSMutableArray按照给定的条件排序, NSArray、NSSet、NSOrderedSet、NSMutableOrderedSet各自有一个输出方法。

2.NSPredicate 谓词筛选, 谓词筛选有很多不同语法,这里用到的是@”SELF.play_time = ‘%@’” ,意思是把这个数组里的play_time字段作为谓词条件,把dataArray这个数组里play_time相同的一组字典放入一个数组里。 最后通过filteredArrayUsingPredicate输出一个重新整理组合后的目标数组。

这是自己这个技术点的一点点总结,后面再说一下自己sqlite的一点点自我总结,。谓词的使用还是挺强大的,他的语法也很多,这里贴一个链接,基本总结了常用的语法。
http://www.jianshu.com/p/88be28860cde

上一篇:Fragment no longer exists for key f0: index 0 下一篇:一次ContentProvider踩坑之旅