Поиск / фильтрация массива пользовательских классов с помощью NSPredicate - PullRequest
6 голосов
/ 26 августа 2011

У меня есть массив, который содержит объекты пользовательского класса, и я хотел бы отфильтровать массив на основе того, содержит ли один из атрибутов классов пользовательскую строку.У меня есть метод, которому передается атрибут, который я хочу найти (столбец) и строка, которую он будет искать (searchString).Вот код, который у меня есть:

NSPredicate *query = [NSPredicate predicateWithFormat:@"%K contains %K", column,   searchString];
NSMutableArray *temp = [displayProviders mutableCopy];
[displayProviders release];
displayProviders = [[temp filteredArrayUsingPredicate:query] mutableCopy];
[temp release];

Однако, он всегда выдает исключение на displayProviders = [[temp FilterArrayUsingPredicate: query] mutableCopy];говоря, что этот класс не соответствует значению ключа для ключа [независимо от searchString].

Есть идеи, что я делаю неправильно?

Ответы [ 3 ]

19 голосов
/ 26 августа 2011
[NSPredicate predicateWithFormat:@"%@ contains %@", column,      searchString];

При использовании подстановки %@ в строке формата предиката полученное выражение будет иметь значение с постоянным значением .Похоже, вы не хотите постоянное значение;скорее, вы хотите, чтобы имя атрибута интерпретировалось как ключевой путь.

Другими словами, если вы делаете это:

NSString *column = @"name";
NSString *searchString = @"Dave";
NSPredicate *p = [NSPredicate predicateWithFormat:@"%@ contains %@", column, searchString];

Это будет эквивалентноto:

p = [NSPredicate predicateWithFormat:@"'name' contains 'Dave'"];

То же самое, что:

BOOL contains = [@"name rangeOfString:@"Dave"].location != NSNotFound;
// "contains" will ALWAYS be false
// since the string "name" does not contain "Dave"

Это явно не то, что вы хотите.Вы хотите эквивалент этого:

p = [NSPredicate predicateWithFormat:@"name contains 'Dave'"];

Чтобы получить это, вы не можете использовать %@ в качестве спецификатора формата.Вместо этого вы должны использовать %K.%K является спецификатором, уникальным для предикатов строк формата, и это означает, что замещенная строка должна интерпретироваться как путь ключа (т. Е. Имя свойства), а не как строка литерала.

Таким образом, ваш код должен быть:

NSPredicate *query = [NSPredicate predicateWithFormat:@"%K contains %@", column, searchString];

Использование @"%K contains %K" также не работает, потому что это то же самое, что:

[NSPredicate predicateWithFormat:@"name contains Dave"]

так же, как:

BOOL contains = [[object name] rangeOfString:[object Dave]].location != NSNotFound;
1 голос
/ 26 августа 2011

Замените %K на %@ в строке предиката,

@"%@ contains %@", column, searchString
0 голосов
/ 31 июля 2013

Это работает для меня

[self.array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"name contains 'Dave'"]];
...