Создание предикатов

Cocoa

Есть три способа создания предиката в Cocoa: используя формат строки, непосредственно в коде, и с шаблоном предиката.

Создание предикатов с помощью формата строки

Вы можете использовать методы класса NSPredicate вида predicateWithFormat... для создания предиката непосредственно из строки. Необходимо определить предикат в виде строки, при необходимости используя подстановки. Во время выполнения выполняются подстановки переменных, если таковые имеются, и в результате эта строка может быть использована для создания соответствующего предиката и выражений объектов. В следующем примере создается соединение предиката с двумя предикатами сравнения.

NSPredicate *predicate = [NSPredicate
    predicateWithFormat:@"(lastName like[cd] %@) AND (birthday > %@)",
            lastNameSearchString, birthdaySearchDate];

(в примере like[cd] означает "без учета регистра и диакритических знаков").

Полное описание синтаксиса строки и список операторов, доступных в разделе "Предикаты, синтаксис формата строки".

Важно. Синтаксис формата строки предиката отличается от синтаксиса регулярных выражений.

Синтаксический анализатор строки предиката разбирает пробельные символы, регистр по отношению к ключевым словам, а также поддерживает вложенные в скобки выражения. Он также поддерживает в стиле printf формат аргументов (например, x% и %@) см. "Форматирование строковых объектов". Переменные обозначаются $ (например, $VARIABLE_NAME).

Синтаксический анализатор не выполняет никакой семантической проверкой типов. Это более простым создание подходящего выражения, но, особенно в случае замены переменных, может привести к ошибке выполнения или вообще к непредсказуемому результату.

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

Строковые константы, переменные и шаблоны

Строковые константы должны быть заключены в кавычки в выражении, одинарные и двойные кавычки являются приемлемыми, но должны работать в паре соответствующим образом (то есть двойные кавычки (") не соответствует одинарным кавычкам (')). Если вы используете подстановку переменных с помощью %@ (например, как firstName like %@) кавычки добавляются автоматически. Если вы используете строковые константы в вашей строке формата, вы должны привести их самостоятельно, как в следующем примере.

NSPredicate *predicate = [NSPredicate
    predicateWithFormat:@"lastName like[c] \"S*\""];

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

NSString *prefix = @"prefix";
NSString *suffix = @"suffix";
NSPredicate *predicate = [NSPredicate
  predicateWithFormat:@"SELF like[c] %@",
  [[prefix stringByAppendingString:@"*"] stringByAppendingString:suffix]];
BOOL ok = [predicate evaluateWithObject:@"prefixxxxxxsuffix"];

В этом примере замена переменной производит строку предиката SELF LIKE[c] "prefix*suffix" и значение реременной ok устанавливается в YES.

Следующий фрагмент, напротив, приводит к строке предиката SELF LIKE[c] "prefix" * "suffix" и предикат выдаст сообщение об ошибке выполнения:

predicate = [NSPredicate
    predicateWithFormat:@"SELF like[c] %@*%@", prefix, suffix];
ok = [predicate evaluateWithObject:@"prefixxxxxxsuffix"];

Булевы значения

Можно указать и проверить равенство логических значений, как показано в следующем примере:

NSPredicate *newPredicate =
    [NSPredicate predicateWithFormat:@"anAttribute == %@",
     [NSNumber numberWithBool:aBool]];
     
NSPredicate *testForTrue =
    [NSPredicate predicateWithFormat:@"anAttribute == YES"];

Динамические имена свойств

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

NSString *attributeName = @"firstName";
NSString *attributeValue = @"Adam";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%@ like %@",
        attributeName, attributeValue];

Формат строки предиката в этом случае вычисляется как "firstName" like "Adam".

Если вы хотите задать динамическое имя свойства, можно использовать %K в строке формата, как показано в следующем фрагменте.

predicate = [NSPredicate predicateWithFormat:@"%K like %@",
        attributeName, attributeValue];

Формат строки предиката в этом случае вычисляется как firstName like "Adam" (обратите внимание, что нет никаких кавычек вокруг firstName).

Создание предикатов непосредственно в коде

Вы можете создать предикаты и экземпляры выражений непосредственно в коде. NSComparisonPredicate и NSCompoundPredicate предоставляют удобные методы, которые позволяют легко создавать соединение и сравнение предикатов. NSComparisonPredicate предоставляет ряд операторов, начиная от простых тестов на равенство до пользовательских функций.

Следующий пример показывает, как создать предикат для представления (revenue >= 1000000) and (revenue < 100000000). Обратите внимание, что то же самое в левой части выражения используется для сравнения предикатов.

NSExpression *lhs = [NSExpression expressionForKeyPath:@"revenue"];

NSExpression *greaterThanRhs = [NSExpression expressionForConstantValue:
    [NSNumber numberWithInt:1000000]];

NSPredicate *greaterThanPredicate = [NSComparisonPredicate
    predicateWithLeftExpression:lhs
    rightExpression:greaterThanRhs
    modifier:NSDirectPredicateModifier
    type:NSGreaterThanOrEqualToPredicateOperatorType
    options:0];
 
NSExpression *lessThanRhs = [NSExpression expressionForConstantValue:
    [NSNumber numberWithInt:100000000]];

NSPredicate *lessThanPredicate = [NSComparisonPredicate
    predicateWithLeftExpression:lhs
    rightExpression:lessThanRhs
    modifier:NSDirectPredicateModifier
    type:NSLessThanPredicateOperatorType
    options:0];

NSCompoundPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:
    [NSArray arrayWithObjects:greaterThanPredicate, lessThanPredicate, nil]];

Недостатком этого метода по-видимому можно считать что, вам придется писать много кода. Преимущество в том, что он менее склонен к орфографии и другим типографским ошибкам, которые могут быть обнаружены только во время выполнения, и это может быть быстрее, чем в зависимости от анализа строк.

Создание предикатов, используя шаблоны предикатов

Шаблоны предиката предлагают хороший компромисс между простыми в использовании, но потенциально подверженными ошибкам строкам формата на основе подхода техники интенсивного и чистого кодирования кода. Шаблон предиката - просто предикат, который включает в себя переменные выражения. (Если вы используете Core Data framework, вы можете использовать инструменты разработки Xcode, чтобы добавить предикат шаблона выбором для запросов к модели. В следующем примере используется формат строки для создания предикатов с правой стороной, которая является переменной выражения.

NSPredicate *predicateTemplate = [NSPredicate
    predicateWithFormat:@"lastName like[c] $LAST_NAME"];

Это эквивалентно созданию непосредственно переменной выражения, как показано в следующем примере.

NSExpression *lhs = [NSExpression expressionForKeyPath:@"lastName"];

NSExpression *rhs = [NSExpression expressionForVariable:@"LAST_NAME"];

NSPredicate *predicateTemplate = [NSComparisonPredicate
    predicateWithLeftExpression:lhs
    rightExpression:rhs
    modifier:NSDirectPredicateModifier
    type:NSLikePredicateOperatorType
    options:NSCaseInsensitivePredicateOption];

Чтобы создать допустимый предикат для оценки объекта, можно использовать NSPredicate метод predicateWithSubstitutionVariables: для прохода по словарю, который содержит переменные, которые будут замещены. (Заметим, что словарь должен содержать пары ключ-значение для всех переменных, указанных в предикате).

NSPredicate *predicate = [predicateTemplate predicateWithSubstitutionVariables:
    [NSDictionary dictionaryWithObject:@"Turner" forKey:@"LAST_NAME"]];

новый предикат возвращаемый этим примером lastName LIKE[c] "Turner".

Поскольку замещаемый словарь должен содержать пары ключ-значение для всех переменных, указанных в предикате, если вы хотите, соответствие nil значению, вы должны предоставить nil значение в словаре, как показано в следующем примере.

NSPredicate *predicate = [NSPredicate
    predicateWithFormat:@"date = $DATE"];
predicate = [predicate predicateWithSubstitutionVariables:
    [NSDictionary dictionaryWithObject:[NSNull null] forKey:@"DATE"]];

новый предикат возвращаемый этим примером date == <null>.

Формат строки, итоги

Важно провести различие между различными типами значений в строке формата. Отметим также, что одинарные или двойные кавычки в переменных (или строке замещающей переменную) служат основанием интерпретировать %@, %K, или $ переменные как литералы в формате строк и так будет предохранять любую подмену.

@"attributeName == %@"
Этот предикат проверяет, является ли значение ключа attributeName таким же, как и значение объекта %@, который подставляется во время работы в качестве аргумента predicateWithFormat:. Обратите внимание, что %@ может быть заполнителем для любого объекта, описание которого действует в предикате, например, экземпляр NSDate, NSNumber, NSDecimalNumber или NSString.

@"%K == %@"
Этот предикат проверяет, является ли значение ключа %K таким же, как значение объекта @%. Переменные поставляются во время выполнения в качестве аргументов predicateWithFormat:.

@"name IN $NAME_LIST"
Это шаблон для предиката, который проверяет, является ли значение ключа с именем в переменной $NAME_LIST (без кавычек), которая подставляется во время выполнения predicateWithSubstitutionVariables:.

@"'name' IN $NAME_LIST"
Это шаблон для предиката, который проверяет наличие постоянной величины 'name' (обратите внимание на кавычки вокруг строки) в переменной $NAME_LIST которая предоставляется во время выполнения predicateWithSubstitutionVariables:.

@"$name IN $NAME_LIST"
Это шаблон для предиката, который рассчитывает значения для заменены (с использованием predicateWithSubstitutionVariables:) для обоих $name и $NAME_LIST.

@"%K == '%@'"
Этот предикат проверяет, является ли значение ключа %K равно строке '%@' (обратите внимание на одинарные кавычки вокруг %@). Ключ с именем %K подставляется во время выполнения в качестве аргумента predicateWithFormat:.

 
 
homeЗаметили ошибкукарта сайта 
   Made on a Mac