Создание предикатов
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