「这是我参与2022首次更文挑战的第21天,活动详情查看:2022首次更文挑战」。
引言
日常开发中,优雅高效的代码离不开Predicate的应用。本文第一部分先介绍下基础知识点,第二部分开始简单的应用。
I iOS Predicate Format String Syntax
其中,左手表达式是一个对象的属性键值(键路径); 逻辑符号是一个基本的逻辑运算符; 右手表达式是约束范围。
1.1 Parser Basics
- Two important format specifiers are %@ and %K.
%@ is a var arg substitution for an object value—often a string, number, or date. %K is a var arg substitution for a key path.
NSString *attributeName = @"firstName";
NSString *attributeValue = @"siting";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K like %@",
attributeName, attributeValue];
1.2 Basic Comparisons
=, ==The left-hand expression is equal to the right-hand expression.
>=, =>The left-hand expression is greater than or equal to the right-hand expression.
<=, =<The left-hand expression is less than or equal to the right-hand expression.
>The left-hand expression is greater than the right-hand expression.
<The left-hand expression is less than the right-hand expression.
!=, <>The left-hand expression is not equal to the right-hand expression.
BETWEEN
The left-hand expression is between, or equal to either of, the values specified in the right-hand side. The right-hand side is a two value array (an array is required to specify order) giving upper and lower bounds. For example, 1 BETWEEN { 0 , 33 }, or INPUT BETWEEN { LOWER, $UPPER }.
In Objective-C, you could create a BETWEEN predicate as shown in the following example:
NSPredicate *betweenPredicate =
[NSPredicate predicateWithFormat: @"attributeName BETWEEN %@", @[@1, @10]];
NSDictionary *dictionary = @{ @"attributeName" : @5 };
BOOL between = [betweenPredicate evaluateWithObject:dictionary];
if (between) {
NSLog(@"between");
}
1.3 Basic Compound Predicates
AND, &&Logical AND.
OR, ||Logical OR.
NOT, !Logical NOT.
1.4 String Comparisons
逻辑运算符与SQL语句中的语法基本相对应,除了最基本的逻辑运算符之外,还有逻辑词IN、CONTAINS、like等。
它们的使用情况如下:
BEGINSWITHThe left-hand expression begins with the right-hand expression.
CONTAINSThe left-hand expression contains the right-hand expression.
ENDSWITHThe left-hand expression ends with the right-hand expression.
LIKE
The left hand expression equals the right-hand expression: ? and * are allowed as wildcard characters, where ? matches 1 character and * matches 0 or more characters.
MATCHES
The left hand expression equals the right hand expression using a regex-style comparison according to ICU v3 (for more details see the ICU User Guide for Regular Expressions).
UTI-CONFORMS-TO
The left hand argument to this operator is an expression that evaluates to a universal type identifier (UTI) you want to match. The right hand argument is an expression that evaluates to a UTI. The comparison evaluates to TRUE if the UTI returned by the left hand expression conforms to the UTI returned by the right hand expression. For information on which types conform to a given type, see System-Declared Uniform Type Identifiers in Uniform Type Identifiers Reference.
The clause A UTI-CONFORMS-TO B provides the same result as employing the UTTypeConformsTo method as follows:
UTTypeConformsTo (A, B)
When evaluating attachments in an app extension item (of type NSExtensionItem), you could use a statement similar to the following:
SUBQUERY (
extensionItems,
$extensionItem,
SUBQUERY (
$extensionItem.attachments,
$attachment,
ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "com.adobe.pdf"
).@count == $extensionItem.attachments.@count
).@count == 1
UTI-EQUALS
The left hand argument to this operator is an expression that evaluates to a universal type identifier (UTI) you want to match. The right hand argument is an expression that evaluates to a UTI. The comparison evaluates to TRUE if the UTI returned by the left hand expression equals the UTI returned by the right hand expression. The clause A UTI-EQUALS B provides the same result as employing the UTTypeEqual method as follows:
UTTypeEqual (A, B)
1.5 Aggregate Operations
ANY, SOME
Specifies any of the elements in the following expression. For example ANY children.age < 18.
ALL
Specifies all of the elements in the following expression. For example ALL children.age < 18.
NONE
Specifies none of the elements in the following expression. For example, NONE children.age < 18. This is logically equivalent to NOT (ANY ...).
IN
Equivalent to an SQL IN operation, the left-hand side must appear in the collection specified by the right-hand side.
For example, name IN { 'Ben', 'Melissa', 'Nick' }. The collection may be an array, a set, or a dictionary—in the case of a dictionary, its values are used. In Objective-C, you could create a IN predicate as shown in the following example:
NSPredicate *inPredicate =
[NSPredicate predicateWithFormat: @"attribute IN %@", aCollection];
where aCollection may be an instance of NSArray, NSSet, NSDictionary, or of any of the corresponding mutable classes.
array[index]
Specifies the element at the specified index in the array array.
array[FIRST]
Specifies the first element in the array array.
array[LAST]
Specifies the last element in the array array.
array[SIZE]
Specifies the size of the array array.
1.6 Identifiers
C style identifier
Any C style identifier that is not a reserved word.
#symbol
Used to escape a reserved word into a user identifier.
[\]{octaldigit}{3}
Used to escape an octal number ( \ followed by 3 octal digits).
[\][xX]{hexdigit}{2}
Used to escape a hex number ( \x or \X followed by 2 hex digits).
[\][uU]{hexdigit}{4}
Used to escape a Unicode number ( \u or \U followed by 4 hex digits).
1.7 Literals
FALSE, NO
Logical false.
TRUE, YES
Logical true.
NULL, NIL
A null value.
SELF
Represents the object being evaluated.
"text"
A character string.
'text'
A character string.
Comma-separated literal array
For example, { 'comma', 'separated', 'literal', 'array' }.
Standard integer and fixed-point notations
For example, 1, 27, 2.71828, 19.75.
Floating-point notation with exponentiation
For example, 9.2e-5.
0x
Prefix used to denote a hexadecimal digit sequence.
0o
Prefix used to denote an octal digit sequence.
0b
Prefix used to denote a binary digit sequence.
1.8 Reserved Words
AND, OR, IN, NOT, ALL, ANY, SOME, NONE, LIKE, CASEINSENSITIVE, CI, MATCHES, CONTAINS, BEGINSWITH, ENDSWITH, BETWEEN, NULL, NIL, SELF, TRUE, YES, FALSE, NO, FIRST, LAST, SIZE, ANYKEY, SUBQUERY, FETCH, CAST, TRUEPREDICATE, FALSEPREDICATE, UTI-CONFORMS-TO, UTI-EQUALS,
II、Boolean Value Predicates
利用NSPredicate 的evaluateWithObject 方法进行校验
NSPredicate在正则表达式的应用
2.1 基本校验例子
#pragma 正则匹配手机号
+ (BOOL)checkTelNumber:(NSString *) telNumber
{
NSString *pattern = @^1+[3578]+\d{9};
NSPredicate *pred = [NSPredicate predicateWithFormat:@SELF MATCHES %@, pattern];
BOOL isMatch = [pred evaluateWithObject:telNumber];
return isMatch;
}
#pragma 正则匹配用户密码6-18位数字和字母组合
+ (BOOL)checkPassword:(NSString *) password
{
NSString *pattern = @^(?![0-9]+$)(?![a-zA-Z]+$)[a-zA-Z0-9]{6,18};
NSPredicate *pred = [NSPredicate predicateWithFormat:@SELF MATCHES %@, pattern];
BOOL isMatch = [pred evaluateWithObject:password];
return isMatch;
}
#pragma 正则匹配用户姓名,20位的中文或英文
+ (BOOL)checkUserName : (NSString *) userName
{
NSString *pattern = @^[a-zA-Z一-龥]{1,20};
NSPredicate *pred = [NSPredicate predicateWithFormat:@SELF MATCHES %@, pattern];
BOOL isMatch = [pred evaluateWithObject:userName];
return isMatch;
}
#pragma 正则匹配用户身份证号15或18位
+ (BOOL)checkUserIdCard: (NSString *) idCard
{
NSString *pattern = @(^[0-9]{15}$)|([0-9]{17}([0-9]|X)$);
NSPredicate *pred = [NSPredicate predicateWithFormat:@SELF MATCHES %@, pattern];
BOOL isMatch = [pred evaluateWithObject:idCard];
return isMatch;
}
#pragma 正则匹员工号,12位的数字
+ (BOOL)checkEmployeeNumber : (NSString *) number
{
NSString *pattern = @^[0-9]{12};
NSPredicate *pred = [NSPredicate predicateWithFormat:@SELF MATCHES %@, pattern];
BOOL isMatch = [pred evaluateWithObject:number];
return isMatch;
}
#pragma 正则匹配URL
+ (BOOL)checkURL : (NSString *) url
{
NSString *pattern = @^[0-9A-Za-z]{1,50};
NSPredicate *pred = [NSPredicate predicateWithFormat:@SELF MATCHES %@, pattern];
BOOL isMatch = [pred evaluateWithObject:url];
return isMatch;
}
2.2 限制UITextField只能输入金额
+ (BOOL)isAmoutshouldChangeCharactersInRange:(NSString*)str{
//匹配以0开头的数字
NSPredicate * predicate0 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",@"^[0][0-9]+$"];
//匹配两位小数、整数
NSPredicate * predicate1 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",@"^(([1-9]{1}[0-9]*|[0])\.?[0-9]{0,2})$"];
return ![predicate0 evaluateWithObject:str] && [predicate1 evaluateWithObject:str] ? YES : NO;
}
/**
限制UITextField只能输入金额的正则表达式
@param textField <#textField description#>
@param range <#range description#>
@param string <#string description#>
@return <#return value description#>
*/
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSInteger len = range.length > 0?([textField.text length] - range.length): ([textField.text length] + [string length]);
if(len > 20){
return false;
}
////
NSString * str = [NSString stringWithFormat:@"%@%@",textField.text,string];
return [QCT_Common isAmoutshouldChangeCharactersInRange:str];
}
2.3 isUrl
+(BOOL)isUrl:(NSString *)url{
NSString *regex =@"[a-zA-z]+://[^\\s]*";
NSPredicate *urlTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
return [urlTest evaluateWithObject:url];
}
- 用法举例:自定义NSURLProtocol, 决定请求是否需要当前协议对象处理
/**
决定请求是否需要当前协议对象处理
*/
+(BOOL)canInitWithRequest:(NSURLRequest *)request{
if ([NSURLProtocol propertyForKey:protocolKey inRequest:request]) {
return NO;
}
NSString * url = request.URL.absoluteString;
return [self isUrl:url];
}
2.4 判断字符串是否为IP地址
/**
* 判断字符串是否为IP地址
* param iPAddress IP地址字符串
* return BOOL 是返回YES,否返回NO
*/
+ (BOOL)isIPAddress:(NSString *)iPAddress{
NSString *pattern = @"^(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5]).(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5]).(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5]).(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])$";
return [self isText:iPAddress pattern:pattern];
}
+ (BOOL)isText:(NSString *)text pattern:(NSString *)pattern{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",pattern];
return [predicate evaluateWithObject:text];
}
III iOS NSPredicate的应用指南之【从数组搜索特定条件的元素】(从数组中筛选type=8的电子签名数据,避免遍历数组 certificateInfoList)
———————————————— 版权声明:本文为CSDN博主「#公众号:iOS逆向」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/z929118967/…
see also
🍅 联系作者: iOS逆向(公号:iosrev)
🍅 作者简介:CSDN 博客专家认证🏆丨全站 Top 50、华为云云享专家认证🏆、iOS逆向公号号主
🍅 简历模板、技术互助。关注我,都给你。