美文网首页Predicate
NSExpression的使用

NSExpression的使用

作者: 想聽丿伱說衹愛我 | 来源:发表于2020-09-10 10:53 被阅读0次

    版本: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]

    相关文章

      网友评论

        本文标题:NSExpression的使用

        本文链接:https://www.haomeiwen.com/subject/twheektx.html