2010-03-24 5 views
2

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

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

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

Это бросает valueForUndefinedKey ошибку. Правильно ли это predicateWithFormat?

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

ответ

2

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

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

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

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

+0

Исправить. Включение 'stringWithFormat:' является тем, что вызывало проблему. См. Мой ответ для полного объяснения. –

3

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

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

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

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

+0

bend0r: Не делайте свертки с короткими краями; когда вам нужно сравнивать строки без учета регистра, используйте сравнение без учета регистра. В этом случае это 'LIKE [c]'. –

+0

Проводковый код, отличный от того, который вы используете, обычно не помогает другим вам помочь. –

1

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

4

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

При создании строки, используя 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: умна. Он видит «aha, a%@ шаблон замены! Это означает, что я могу вывести аргумент из списка аргументов и поместить его в поле и использовать его как есть».Это именно то, что он собирается делать. Он должен вывести значение searchText из списка аргументов, поместить его в NSExpression и вставить его непосредственно в синтаксическое дерево выражений.

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

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

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