版本:iOS13.7
一、简介
表达式NSExpression是谓词NSPredicate实现的核心,常用于比较谓词NSComparisonPredicate,点击NSComparisonPredicate的使用了解。
调用expressionValueWithObject
时,将对表达式求值,并返回一个可处理的值。
表达式可以是从常量到方法调用的任何内容。
表达式的结果指的是
expressionValueWithObject
的返回值。
表达式的参数对象指的是expressionValueWithObject
传入的object或NSPredicate.evaluateWithObject
传入的object。
表达式的bindings字典指的是expressionValueWithObject
传入的context和NSPredicate.evaluateWithObject
传入的bindings
二、NSExpression的API
@interface NSExpression : NSObject <NSSecureCoding, NSCopying>
//通过格式化字符串创建一个表达式
//字符串中的%@占位符将由arguments的元素替换
//详见说明1
+ (NSExpression *)expressionWithFormat:(NSString *)expressionFormat
argumentArray:(NSArray *)arguments;
//通过格式化字符串创建一个表达式
//详见说明1
+ (NSExpression *)expressionWithFormat:(NSString *)expressionFormat, ...;
//通过格式化字符串创建一个表达式
//字符串中的%@占位符将由argList的元素替换
+ (NSExpression *)expressionWithFormat:(NSString *)expressionFormat
arguments:(va_list)argList;
//通过常量创建表达式
//NSExpression.constantValue为obj
+ (NSExpression *)expressionForConstantValue:(nullable id)obj;
//通过参数对象创建表达式
//相当于[NSExpression expressionWithFormat:@"SELF"]
+ (NSExpression *)expressionForEvaluatedObject;
//通过bindings字典的key创建表达式
//详见例1
+ (NSExpression *)expressionForVariable:(NSString *)string;
//通过参数对象的keypath创建表达式
//详见例2
+ (NSExpression *)expressionForKeyPath:(NSString *)keyPath;
//通过函数名创建表达式
//parameters里面为0至2个NSExpression
//详见例3
+ (NSExpression *)expressionForFunction:(NSString *)name arguments:(NSArray *)parameters;
//通过传入的表达式的结果的集合创建表达式
//详见例4
+ (NSExpression *)expressionForAggregate:(NSArray<NSExpression *> *)subexpressions;
//创建一个表达式,该表达式的结果为left和right结果的集合的并集
//该表达式的NSExpression.leftExpression为left,NSExpression.rightExpression为right
//详见例5
+ (NSExpression *)expressionForUnionSet:(NSExpression *)left with:(NSExpression *)right;
//创建一个表达式,该表达式的结果为left和right结果的集合的交集
//详见例5
+ (NSExpression *)expressionForIntersectSet:(NSExpression *)left with:(NSExpression *)right;
//创建一个表达式,该表达式的结果为left和right结果的集合的析取(不太明白析取的意思~_~!)
+ (NSExpression *)expressionForMinusSet:(NSExpression *)left with:(NSExpression *)right;
//todo
+ (NSExpression *)expressionForSubquery:(NSExpression *)expression
usingIteratorVariable:(NSString *)variable
predicate:(NSPredicate *)predicate;
//创建一个表达式,表达式的结果为选择器的返回值
//target 选择器所属的对象
//name 选择器名
//parameters 选择器需要的参数,类型为NSArray<NSExpression *>
//详见例6
+ (NSExpression *)expressionForFunction:(NSExpression *)target
selectorName:(NSString *)name
arguments:(nullable NSArray *)parameters;
//todo
+ (NSExpression *)expressionForAnyKey;
//通过block创建一个表达式,表达式的结果为block返回的值
//详见例7
+ (NSExpression *)expressionForBlock:(id (^)(id _Nullable evaluatedObject, NSArray<NSExpression *> *expressions, NSMutableDictionary * _Nullable context))block
arguments:(nullable NSArray<NSExpression *> *)arguments;
//创建一个表达式,通过谓词评估结果的真假来决定使用trueExpression还是falseExpression
//谓词所需的评估对象为expressionValueWithObject传入的object
//详见例8
+ (NSExpression *)expressionForConditional:(NSPredicate *)predicate
trueExpression:(NSExpression *)trueExpression
falseExpression:(NSExpression *)falseExpression;
//通过表达式类型来初始化
//详见说明2
- (instancetype)initWithExpressionType:(NSExpressionType)type;
//初始化
- (nullable instancetype)initWithCoder:(NSCoder *)coder;
//表达式的类型 只读 详见说明2
@property (readonly) NSExpressionType expressionType;
//表达式的常数值 只读
@property (nullable, readonly, retain) id constantValue;
//表达式的参数对象的keyPath路径 只读
@property (readonly, copy) NSString *keyPath;
//表达式的函数名 只读
@property (readonly, copy) NSString *function;
//表达式的bindings字典的key 只读
@property (readonly, copy) NSString *variable;
//表达式要调用函数的对象 只读
@property (readonly, copy) NSExpression *operand;
//表达式要调用函数的参数 只读
@property (nullable, readonly, copy) NSArray<NSExpression *> *arguments;
//表达式的集合
@property (readonly, retain) id collection;
//表达式要满足的谓词
@property (readonly, copy) NSPredicate *predicate;
//集合表达式的左表达式
@property (readonly, copy) NSExpression *leftExpression;
//集合表达式的右表达式
@property (readonly, copy) NSExpression *rightExpression;
//条件表达式的谓词评估为真时的表达式
@property (readonly, copy) NSExpression *trueExpression;
//条件表达式的谓词评估为假时的表达式
@property (readonly, copy) NSExpression *falseExpression;
//表达式的block
@property (readonly, copy) id (^expressionBlock)(id _Nullable, NSArray<NSExpression *> *, NSMutableDictionary * _Nullable);
//使用参数对象和bindings字典来评估表达式,并返回结果
- (nullable id)expressionValueWithObject:(nullable id)object
context:(nullable NSMutableDictionary *)context;
//强制使用已安全解码的表达式以允许评估
- (void)allowEvaluation;
@end
- 说明1
NSExpression *exp = [NSExpression expressionWithFormat:@"%@" argumentArray:@[@"test"]];
等价于
NSExpression *exp = [NSExpression expressionWithFormat:@"%@", @"test"];
测试发现,当有多个%@时运行会崩溃,[NSExpression expressionWithFormat:@"a%@a", @"test"]
这样写也会崩溃。
- 说明2
typedef NS_ENUM(NSUInteger, NSExpressionType) {
//返回相同值的表达式
NSConstantValueExpressionType = 0,
//返回参数对象本身的表达式
NSEvaluatedObjectExpressionType,
//返回bindings字典中对应key的值的表达式
NSVariableExpressionType,
//返回参数对象的对应keyPath的值的表达式
NSKeyPathExpressionType,
//返回函数返回值的表达式
NSFunctionExpressionType,
//返回两表达式结果的并集的表达式
NSUnionSetExpressionType,
//返回两表达式结果的交集的表达式
NSIntersectSetExpressionType,
//返回两表达式结果的析取的表达式
NSMinusSetExpressionType ,
//todo
NSSubqueryExpressionType = 13,
//返回两表达式结果的集合的表达式
NSAggregateExpressionType = 14,
//todo
NSAnyKeyExpressionType = 15,
//返回block的返回值的表达式
NSBlockExpressionType = 19,
//根据谓词评估真假来决定的表达式
NSConditionalExpressionType = 20
};
- 例1
NSExpression *left1 = [NSExpression expressionForVariable:@"key1"];
NSExpression *right1 = [NSExpression expressionWithFormat:@"%@", @[@"aaa", @"bbb", @"ccc"]];
NSComparisonPredicate *comparison1 = [NSComparisonPredicate predicateWithLeftExpression:left1
rightExpression:right1 modifier:NSDirectPredicateModifier
type:NSInPredicateOperatorType options:NSCaseInsensitivePredicateOption];
NSLog(@"%@", [comparison1 predicateFormat]);
BOOL success1 = [comparison1 evaluateWithObject:nil substitutionVariables:@{@"key1":@"aaa"}];
NSLog(@"%@", @(success1));
输出:
$key1 IN[c] {"aaa", "bbb", "ccc"}
1
可以左表达式通过$声明了一个变量key1,该变量从substitutionVariables:传入的字典中取值。
- 例2
NSExpression *left1 = [NSExpression expressionForKeyPath:@"key1.key2"];
NSExpression *right1 = [NSExpression expressionWithFormat:@"%@", @[@"aaa", @"bbb", @"ccc"]];
NSComparisonPredicate *comparison1 = [NSComparisonPredicate predicateWithLeftExpression:left1
rightExpression:right1 modifier:NSDirectPredicateModifier
type:NSInPredicateOperatorType options:NSCaseInsensitivePredicateOption];
NSLog(@"%@", [comparison1 predicateFormat]);
BOOL success1 = [comparison1 evaluateWithObject:@{@"key1":@{@"key2":@"bbb"}}];
NSLog(@"%@", @(success1));
输出:
key1.key2 IN[c] {"aaa", "bbb", "ccc"}
1
@{@"key1":@{@"key2":@"bbb"}}
会调用valueForKeyPath:key1.key2
取出值bbb
- 例3
NSExpression *left1 = [NSExpression expressionWithFormat:@"SELF"];
//创建一个常数表达式
NSExpression *sun = [NSExpression expressionForConstantValue:@[@2, @4, @6]];
//sum:时需要arguments中存在一个常数值为NSNumber的集合的表达式
NSExpression *right1 = [NSExpression expressionForFunction:@"sum:" arguments:@[sun]];
NSComparisonPredicate *comparison1 = [NSComparisonPredicate predicateWithLeftExpression:left1
rightExpression:right1 modifier:NSDirectPredicateModifier
type:NSLessThanPredicateOperatorType options:NSCaseInsensitivePredicateOption];
NSLog(@"%@", [comparison1 predicateFormat]);
BOOL success1 = [comparison1 evaluateWithObject:@10];
NSLog(@"%@", @(success1));
输出:
SELF <[c] sum:({2, 4, 6})
1
// name meter array contents returns
// sum: NSExpression instances representing numbers NSNumber
// multiply:by: two NSExpression instances representing numbers NSNumber
上面为官方注释,表示sum: 方法需要传入一个NSExpression实例,该实例的常数为numbers(NSNubmer的集合),并在调用expressionValueWithObject
返回NSNumber。
multiply:by: 则表示要传入两个NSExpression实例,常数也为NSNubmer的集合,并返回NSNumber。
支持的函数方法
统计
sum:
求和
count:
个数
min:
最小值
max:
最大值
average:
平均数
median:
中位数
mode:
众数(出现次数最多的数)
stddev:
标准差
基本运算
add:to:
加
from:subtract:
减
multiply:by:
乘
divide:by:
除
高级运算
modulus:by:
模数
sqrt:
开平方
log:
对数
ln:
自然对数
raise:toPower:
乘方
exp:
指数
数字处理
floor:
向下取整
ceiling:
向上取整
abs:
绝对值
trunc:
取整(直接截去小数)
位计算
bitwiseAnd:with:
按位与
bitwiseOr:with:
按位或
bitwiseXor:with:
按位异或
leftshift:by:
按位左移
rightshift:by:
按位右移
onesComplement:
按位取反
其他
uppercase:
字符串大写
lowercase:
字符串小写
canonical:
random
随机数
randomn:
随机数(小于传入的NSNumber)
now
当前时间
noindex:
distanceToLocation:fromLocation:
两坐标的距离
length:
字符串的长度
- 例4
NSExpression *e1 = [NSExpression expressionForConstantValue:@"aaa"];
id v1 = [e1 expressionValueWithObject:nil context:nil];
NSExpression *e2 = [NSExpression expressionForConstantValue:@20];
id v2 = [e2 expressionValueWithObject:nil context:nil];
NSExpression *e3 = [NSExpression expressionForAggregate:@[e1, e2]];
id v3 = [e3 expressionValueWithObject:nil context:nil];
NSLog(@"%@ %@ %@", v1, v2, v3);
输出:
aaa 20 (
aaa,
20
)
- 例5
NSExpression *e1 = [NSExpression expressionForConstantValue:@[@10, @20]];
id v1 = [e1 expressionValueWithObject:nil context:nil];
NSExpression *e2 = [NSExpression expressionForConstantValue:@[@20, @30]];
id v2 = [e2 expressionValueWithObject:nil context:nil];
NSExpression *e3 = [NSExpression expressionForUnionSet:e1 with:e2];
id v3 = [e3 expressionValueWithObject:nil context:nil];
NSExpression *e4 = [NSExpression expressionForIntersectSet:e1 with:e2];
id v4 = [e4 expressionValueWithObject:nil context:nil];
NSLog(@"%@ %@", v1, v2);
NSLog(@"%@ %@", v3, v4);
输出:
(
10,
20
) (
20,
30
)
{(
30,
10,
20
)} {(
20
)}
- 例6
NSExpression *r = [NSExpression expressionForFunction:[NSExpression expressionWithFormat:@"SELF"]
selectorName:@"function:withb:"
arguments:@[[NSExpression expressionForConstantValue:@"aa"],
[NSExpression expressionForConstantValue:@"bb"]]];
id rv = [r expressionValueWithObject:self context:nil];
NSLog(@"%@", rv);
- (NSString *)function:(NSString *)a withb:(NSString *)b {
NSLog(@"a= %@ b = %@", a, b);
return [NSString stringWithFormat:@"%@%@", a, b];
}
输出:
a= aa b = bb
aabb
可见,arguments的值为function:withb:
方法的两个入参的值,function:withb:
的返回值为expressionValueWithObject
的返回值,expressionValueWithObject
的object需要传self表示对象self的function:withb:
- 例7
NSExpression *aaa = [NSExpression expressionForBlock:^id _Nonnull(id _Nullable evaluatedObject, NSArray<NSExpression *> * _Nonnull expressions, NSMutableDictionary * _Nullable context) {
NSLog(@"%@ %@ %@", evaluatedObject, expressions, context);
return @"bbb";
} arguments:@[[NSExpression expressionForConstantValue:@10]]];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:@{@"key1":@"value1"}];
id aaav = [aaa expressionValueWithObject:self context:dict];
NSLog(@"%@", aaav);
输出:
<Predicate: 0x7ff5d5d2d7d0> (
10
) {
key1 = value1;
}
bbb
可见block的evaluatedObject为expressionValueWithObject
传入的object,block的expressions为expressionForBlock
传入的arguments,block的context为expressionValueWithObject
传入的context,block的返回值为expressionValueWithObject
的返回值
- 例8
NSPredicate *pp = [NSPredicate predicateWithFormat:@"SELF < 30"];
NSExpression *bbb = [NSExpression expressionForConditional:pp
trueExpression:[NSExpression expressionForConstantValue:@10]
falseExpression:[NSExpression expressionForConstantValue:@20]];
id bbbv = [bbb expressionValueWithObject:@20 context:nil];
NSLog(@"%@", bbbv);
输出:
10
因为20<30为真,所以bbb = trueExpression,即[NSExpression expressionForConstantValue:@10]
网友评论