Chaining replacements don't work in NSPredicate

一笑奈何 提交于 2020-01-06 14:44:27

问题


The following code raises a question

NSPredicate * myPred = [NSPredicate predicateWithFormat:@"$my_var.employees.@count == 3"];

NSExpression * myExpr = [NSExpression    expressionForKeyPath:@"$my_var.test"] ;

 NSPredicate * myPredBis = [myPred predicateWithSubstitutionVariables:@{@"my_var" : myExpr}] ;



NSExpression * myExpr2 = [NSExpression    expressionForKeyPath:@"self"] ;

NSPredicate * myFinalPred = [myPredBis predicateWithSubstitutionVariables:@{@"my_var": myExpr2}];

NSLog(@"%@", myFinalPred) ;

It prints

$my_var.test.employees.@count == 3

But we would like

self.test.employees.@count == 3

Why does this happen?


回答1:


This is only a partial answer, but perhaps it helps to put you on the right path.

First, substituting $my_var by [NSExpression expressionForKeyPath:@"$my_var.test"] does not work, because the latter expression treats $my_var as a plain key, not as a variable.

But you can substitute one variable by another variable, using expressionForVariable:

NSPredicate * myPred = [NSPredicate predicateWithFormat:@"$my_var.employees.@count == 3"];
NSExpression * myExpr = [NSExpression expressionForVariable:@"another_var"] ;
NSPredicate * myPredBis = [myPred predicateWithSubstitutionVariables:@{@"my_var" : myExpr}] ;

Second, [NSExpression expressionForKeyPath:@"self"] treats "self" as an ordinary key, not as "the" self, i.e. the object onto which the predicate is applied. You probably want:

NSExpression * myExpr2 = [NSExpression expressionForEvaluatedObject];

instead. Now you can chain the substitution:

NSPredicate * myFinalPred = [myPredBis predicateWithSubstitutionVariables:@{@"another_var": myExpr2}];
NSLog(@"%@", myFinalPred);

Output: employees.@count == 3 (the "self" part is just not printed).


OK, here is the solution to your problem. The tricky part is the second step. I did not find a direct way to build a key-path expression that consists of a variable ($my_var) combined with a normal key (test). But it can be done by taking the left-hand side of a predicate:

NSPredicate * myPred = [NSPredicate predicateWithFormat:@"$my_var.employees.@count == 3"];
NSLog(@"%@", myPred) ;
// $my_var.employees.@count == 3            

NSExpression *myExpr = [(NSComparisonPredicate *)[NSPredicate predicateWithFormat:@"$my_var.test == 0"] leftExpression];
NSPredicate * myPredBis = [myPred predicateWithSubstitutionVariables:@{@"my_var" : myExpr}] ;
NSLog(@"%@", myPredBis) ; 
// $my_var.test.employees.@count == 3           

NSExpression * myExpr2 = [NSExpression expressionForEvaluatedObject];
NSPredicate * myFinalPred = [myPredBis predicateWithSubstitutionVariables:@{@"my_var": myExpr2}];
NSLog(@"%@", myFinalPred) ;            
// test.employees.@count == 3


来源:https://stackoverflow.com/questions/21823339/chaining-replacements-dont-work-in-nspredicate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!