ПредикатWithFormat против stringWithFormat: первый должен делать то же самое, что и второй? - PullRequest
3 голосов
/ 30 августа 2011

У меня есть массив с именами файлов, и я хочу найти все имена, которые заканчиваются, например, 00001.trc , когда traceNum равно 1. Я попробовал это:

NSPredicate *tracePredicate = [NSPredicate predicateWithFormat:@"SELF ENDSWITH \"%05d.trc\"", traceNum];

и мой предикат был SELF ENDSWITH "%05d.trc" вместо SELF ENDSWITH "00001.trc"

Я попробовал это:

NSPredicate *tracePredicate = [NSPredicate predicateWithFormat:@"SELF ENDSWITH %@%05d.trc%@", @"\"", traceNum, @"\""];

и получил исключение: Unable to parse the format string "SELF ENDSWITH %@%05d.trc%@".

Так что япопробовал это:

NSPredicate *tracePredicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"SELF ENDSWITH \"%05d.trc\"", traceNum]];

и все работает.

Так что мне действительно нужно stringWithFormat в дополнение к predicateWithFormat или есть что-то, что я не правильно делаю при создании моего предиката?

1 Ответ

5 голосов
/ 30 августа 2011

Вы правы; predicateWithFormat: не совсем то же самое, что stringWithFormat:.

Это отличается по нескольким основным причинам:

  1. На самом деле это не создание новой строки. Он просто просматривает строку формата и видит, что следует заменить следующим образом, выталкивает это из va_list и помещает его в соответствующий NSExpression объект.
  2. Он должен поддерживать спецификатор формата, который не NSString: %K. Вот как вы подставляете путь ключа. Если вы попытаетесь заменить имя свойства с помощью %@, оно будет фактически интерпретировано как буквенная строка, а не как имя свойства.
  3. Использование ограничений форматирования (я не уверен, каков правильный термин), таких как 05 в %05d, не поддерживается. С одной стороны, это не имеет смысла. NSPredicate выполняет числовые сравнения (в этом случае 00005 - то же самое, что и 5, и, таким образом, заполнение нулями не имеет значения) и сравнения строк (в которых вы можете просто отформатировать строку самостоятельно, прежде чем передать ее NSPredicate ). (Он выполняет другие сравнения, например, операции сбора, но сейчас я их пропускаю)

Итак, как ты делаешь то, что пытаешься сделать? Лучший способ будет выглядеть так:

NSString *trace = [NSString stringWithFormat:@"%05d.trc", traceNum];
NSPredicate *p = [NSPredicate predicateWithFormat:@"SELF ENDSWITH %@", trace];

Таким образом, вы можете делать все необходимое форматирование, но при этом использовать более правильный подход - передавать константную строку в качестве формата предиката.

...