2013-08-30 2 views
2

Прежде всего: извините, если заголовок не очень ясен, я не мог задать свой вопрос короткими словами!NSPredicate для нескольких совпадений в NSFetchRequest

Пожалуйста, рассмотрим следующий сценарий:
- Вы используете Core Data для хранения объектов
- Вы хотите, чтобы принести объектов из контекста
- Вы хотите включить предикат только получать объекты с определенными свойствами
- У вас есть NSDictionary, содержащий пары ключ-значение, где ключ представляет имя свойства, а значение представляет собой нужное значение в соответствии с

Как лучше всего достичь этого?

настоящее время у меня следующий, который является быстрым и, вероятно, неэффективным способом достижения этой цели:

NSDictionary *attributes = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects:@"value1", @"value2", nil] forKeys: [NSArray arrayWithObjects:@"attr1", @"attr2", nil] ]; 

// Build predicate format 
NSString *predicate = @""; 
NSMutableArray *predicateArguments = [[NSMutableArray alloc] init]; 
int index = 0; 
for (NSString *key in attributes) { 
    NSString *value = [attributes objectForKey: key]; 
    predicate = [predicate stringByAppendingFormat: @"(%@ = %@) %@", key, @"%@", index == [attributes count]-1 ? @"" : @"AND "]; 
    [predicateArguments addObject: value]; 
    index++; 
} 

NSPredicate *matchAttributes = [NSPredicate predicateWithFormat:predicate argumentArray:predicateArguments]; 

-

Есть более короткий или более эффективный способ достижения этого предиката?

Обратите внимание, что блок предикаты не вариант из-за не поддерживается NSFetchRequest (Core Data)

ответ

4

немного короче и, возможно, более элегантный способ заключается в использовании NSCompoundPredicate:

NSDictionary *attributes = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects:@"value1", @"value2", nil] forKeys: [NSArray arrayWithObjects:@"attr1", @"attr2", nil] ]; 

// Build array of sub-predicates: 
NSMutableArray *subPredicates = [[NSMutableArray alloc] init]; 
for (NSString *key in attributes) { 
    NSString *value = [attributes objectForKey: key]; 
    [subPredicates addObject:[NSPredicate predicateWithFormat:@"%K = %@", key, value]]; 
} 
// Combine all sub-predicates with AND: 
NSPredicate *matchAttributes = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates]; 

ДОБАВЛЕНО: Даже лучше (благодаря Paul.s):

NSMutableArray *subPredicates = [[NSMutableArray alloc] init]; 
[attributes enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { 
    [subPredicates addObject:[NSPredicate predicateWithFormat:@"%K = %@", key, value]]; 
}]; 
NSPredicate *matchAttributes = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates]; 
+2

Вы могли бы сделать это немного (1 строка) короче и, наиболее вероятно, более эффективно с использованием нумерации блоков [атрибуты enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL * stop) { [subPredicates addObject: [предикат NSPredicateWithFormat: @ "% K =% @", ключ, значение]]; }]; ' –

+0

@ Paul.s: Хорошая идея! –

+0

Спасибо за решения, ребята, очень полезно. Я скопировал комментарий Paul.s в ответ для будущих зрителей, если они пропустят комментарий! – Joshua

Смежные вопросы