Создание предикатов
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:
.
No comments:
Post a Comment