嵌套的NSPredicate predicateWithBlock不起作用

时间:2014-10-09 03:54:41

标签: ios objective-c

我有一个对象数组,而这些对象又有另一个对象数组(第二级),我的要求是根据第二级的值进行过滤。所以我使用嵌套的predicateWithBlock,但我没有得到所需的输出。

NSMutableArray *topLevelArray;
[topLevelArray filterUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
    NSPredicate *pred = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
        CustomType2 *obj2 = (CustomType2 *)evaluatedObject;
        if ([obj2.name rangeOfString:searchText options:NSCaseInsensitiveSearch].location != NSNotFound)
        {
            return YES;
        }
        else
        {
            return NO;
        }
    }];
    CustomType1 *obj1 = (CustomType1 *)evaluatedObject;
    [obj1.customType2 filteredSetUsingPredicate:pred];
    return YES;
}]];

输入:

topLevelArray = {
  [CustomType1.name = "Alpha",
    CustomType1.customType2 = {
      [CustomType2.name = "Apple"], 
      [CustomType2.name = "Banana"], 
      [CustomType2.name = "Cocoplum"]}
  ],
  [CustomType1.name = "Beta",
    CustomType1.customType2 = {
      [CustomType2.name = "Asparagus"], 
      [CustomType2.name = "Broccoli"]}
  ],
  [CustomType1.name = "Gama",
    CustomType1.customType2 = {
      [CustomType2.name = "Aligator"]}
  ]};


输出:

    searchText = @"Bro";
    topLevelArray = {
      [CustomType1.name = "Alpha",
        CustomType1.customType2 = {
          [CustomType2.name = "Apple"], 
          [CustomType2.name = "Banana"], 
          [CustomType2.name = "Cocoplum"]}
      ],
      [CustomType1.name = "Beta",
        CustomType1.customType2 = {
          [CustomType2.name = "Asparagus"], 
          [CustomType2.name = "Broccoli"]}
      ],
      [CustomType1.name = "Gama",
        CustomType1.customType2 = {
          [CustomType2.name = "Aligator"]}
      ]};

预期输出:

searchText = @"Bro";
topLevelArray = {
  [CustomType1.name = "Alpha",
    CustomType1.customType2 = {nil}
  ],
  [CustomType1.name = "Beta",
    CustomType1.customType2 = {
      [CustomType2.name = "Broccoli"]}
  ],
  [CustomType1.name = "Gama",
    CustomType1.customType2 = {nil}
  ]};

1 个答案:

答案 0 :(得分:0)

我怀疑你必须遍历你的数组,为每个对象应用一个谓词:

NSArray *topLevelArray = @[[CustomType1 typeOneWithName:@"Alpha" typeTwoObjects:@[[CustomType2 typeTwoWithName:@"Apple"],[CustomType2 typeTwoWithName:@"Banana"],[CustomType2 typeTwoWithName:@"Cocoplum"]]],
                           [CustomType1 typeOneWithName:@"Beta"  typeTwoObjects:@[[CustomType2 typeTwoWithName:@"Asparagus"],[CustomType2 typeTwoWithName:@"Broccoli"]]],
                           [CustomType1 typeOneWithName:@"Gamma" typeTwoObjects:@[[CustomType2 typeTwoWithName:@"Aligator"]]]];

NSString *searchTerm = @"Bro";
NSPredicate *titlePredicate = [NSPredicate predicateWithFormat:@"name like[cd] %@", [NSString stringWithFormat:@"*%@*", searchTerm]];
NSMutableArray *results = [NSMutableArray array];
[topLevelArray enumerateObjectsUsingBlock:^(CustomType1 *obj, NSUInteger idx, BOOL *stop) {
    [results addObject:[CustomType1 typeOneWithName:obj.name typeTwoObjects:[obj.typeTwoObjects filteredArrayUsingPredicate:titlePredicate]]];
}];

NSLog(@"topLevelArray = %@", topLevelArray);
NSLog(@"Search for '%@' = %@", searchTerm, results);

哪个收益率:

2014-10-08 20:35:05.173 MyApp[3577:1940746] topLevelArray = (
    "<CustomType1 0x15e545d0; name='Alpha'; typeTwoObjects=[<CustomType2 0x15e774b0; name='Apple'>, <CustomType2 0x15e70840; name='Banana'>, <CustomType2 0x15e66740; name='Cocoplum'>]>",
    "<CustomType1 0x15e52c70; name='Beta'; typeTwoObjects=[<CustomType2 0x15e74ed0; name='Asparagus'>, <CustomType2 0x15e74600; name='Broccoli'>]>",
    "<CustomType1 0x15e50290; name='Gamma'; typeTwoObjects=[<CustomType2 0x15e52c80; name='Aligator'>]>"
)
2014-10-08 20:35:05.196 MyApp[3577:1940746] Search for 'Bro' = (
    "<CustomType1 0x15e7a090; name='Alpha'; typeTwoObjects=[]>",
    "<CustomType1 0x15e7a2e0; name='Beta'; typeTwoObjects=[<CustomType2 0x15e74600; name='Broccoli'>]>",
    "<CustomType1 0x15e7a2f0; name='Gamma'; typeTwoObjects=[]>"
)

上面我建立了一个新的对象数组。您可以轻松改变原始数组。例如,将上面的枚举循环替换为:

[topLevelArray enumerateObjectsUsingBlock:^(CustomType1 *obj, NSUInteger idx, BOOL *stop) {
    obj.typeTwoObjects = [obj.typeTwoObjects filteredArrayUsingPredicate:titlePredicate];
}];

这显然会丢弃任何与谓词不匹配的数据,但也许这就是你想要做的事情。