NSP Предикат и массивы - PullRequest
       31

NSP Предикат и массивы

2 голосов
/ 24 марта 2010

У меня короткий вопрос. У меня есть NSArray, заполненный Cars (который наследуется от NSObject). Car имеет @property NSString *engine (также считается @synthesize)

Теперь я хочу отфильтровать массив, используя NSPredicate:

predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"(engine like %@)", searchText]];
newArray = [ArrayWithCars filteredArrayUsingPredicate:predicate];

Это выдает ошибку valueForUndefinedKey. * predicateWithFormat правильно?

Спасибо за ваши ответы.

Ответы [ 4 ]

4 голосов
/ 26 сентября 2011

Вот реальная причина, почему она не работает:

Когда вы строите строку, используя stringWithFormat:, она будет выглядеть примерно так:

@"engine like searchText"

Затем вы передаете его predicateWithFormat:, который увидит, что как левая, так и правая части сравнения представляют собой не заключенные в кавычки строки, что означает, что он будет интерпретировать их так, как если бы они были keypaths .

Когда этот код запускается, он будет делать:

id leftValue = [object valueForKey:@"engine"];
id rightValue = [object valueForKey:@"searchText"];
return (leftValue is like rightValue);

Исключением является ваш объект, жалующийся на то, что у него нет метода с именем "searchText", что является правильным.

Сравните это с тем, что вы взяли вызов stringWithFormat: и просто поместили все прямо в predicateWithFormat::

NSPredicate *p = [NSPredicate predicateWithFormat:@"engine like %@", searchText];

predicateWithFormat: умный. Он видит «ага, шаблон замены %@! Это означает, что я могу вытолкнуть аргумент из списка аргументов, собрать его и использовать как есть». Это именно то, что он собирается сделать. Он вытолкнет значение searchText из списка аргументов, поместит его в NSExpression и вставит его непосредственно в проанализированное дерево выражений.

Самое интересное, что создаваемое выражение будет выражением с постоянным значением . Это означает, что это буквальная ценность; не путь ключа, не коллекция и т. д. Это будет буквальная строка. Затем, когда ваш предикат запускается, он собирается сделать:

id leftValue = [object valueForKey:@"engine"];
id rightValue = [rightExpression constantValue];
return (leftValue is like rightValue);

И , что является правильным, а также поэтому вы не должны пропускать материал через stringWithFormat:, прежде чем передать его в predicateWithFormat:.

3 голосов
/ 24 марта 2010

К, я нашел ошибку.

predicate = [NSPredicate predicateWithFormat:@"engine like *%@*", searchText];

работает правильно. ** пропали без вести. Кроме того, ваш searchText должен быть заглавным.

@ Josuhua это не настоящий код, просто чтобы представить мою проблему

2 голосов
/ 24 марта 2010

Во-первых, ваш код более многословен, чем необходимо, что всегда открывает вам возможность того, что это неправильно. Попробуйте:

predicate = [NSPredicate predicateWithFormat:@"engine like %@", searchText];

Во-вторых, «ArrayWithCars» выглядит как имя класса (по соглашению классы начинаются с верхнего регистра). Это на самом деле класс или неправильно названная локальная переменная (например, «arrayWithCars» или просто «cars»)?

В-третьих, какая именно ошибка? Какой ключ не определен? Не перефразируйте ошибки, когда просите других о помощи - мы не увидим то, что вы видите, если вы не покажете нам.

1 голос
/ 26 сентября 2011

Попробуйте по этой ссылке . Возможно, вам известны различные способы использования NSPredicate

...