2014-10-09 51 views
0

我有一个对象数组,它又有另一个对象数组(第二级),我的要求是根据第二级的值做一个过滤器。所以我使用嵌套的predicateWithBlock,但我没有得到所需的输出。嵌套的NSPredicate 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} 
    ]}; 
+0

注意'[filteredSetUsingPredicate:]'和'[filterUsingPredicate:]' – borrrden 2014-10-09 04:18:31

+0

'之间的区别'if(something)return YES;否则返回NO;'哦不...'为什么你不能'返回一些东西;' – 2014-10-09 04:35:41

+0

你需要搜索customtype2对象中的数据,我是对的。 – 2014-10-09 04:52:15

回答

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]; 
}]; 

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

+0

感谢您的回应。但是我的自定义对象具有多个属性,对于'results'数组的新对象初始化每个值都无效。有没有其他解决方案? – immasara 2014-10-10 03:24:10

+0

@immasara显然,你可以改变现有的对象数组,而不是创建一个新的'CustomType1'对象数组。在修改后的答案中查看最终的代码片段。 – Rob 2014-10-10 03:46:02

+0

自定义对象数组正在被擦除,因为mutableCopy方法不会给出重复对象,而是执行参考副本。 – immasara 2014-10-11 00:12:31