Objective C NSPredicate两个属性的总和

时间:2018-02-07 15:26:00

标签: ios objective-c sum operators nspredicate

我试图创建一个NSPredicate,它可以处理两个属性的总和,并将它与对象的另一个属性进行比较:

Object.property1 + Object.property2< Object.property3

我尝试过(%K +%K)< %K但没有成功。

PS:甚至可以使一些属性为空。

我试图避免制作大量的复合谓词。

谢谢, 林

2 个答案:

答案 0 :(得分:2)

假设您使用的是SQLite持久性存储,则fetch谓词将转换为等效的SQLite WHERE子句。因此,NULL值的处理由SQLite确定。来自SQLite documentation

  

将任何内容添加到null都会为null

因此,如果谓词中的任何属性为NULL,则总和将为NULL。 Predicate Programming Guide也明确表示必须单独测试NULL值:

  

比较谓词与null匹配除null(nil)或NSNull null值之外的任何值....如果要匹配空值,除了其他比较之外,还必须包含特定的测试... < / p>

因此,您必须在谓词中显式测试空值,正如@ Kamil.S在他的回答中所做的那样。有一种方法可以使它更容易阅读和处理:用条件表达式(相当于property1 == nil ? 0 : property1)替换属性值。您可以使用NSExpressionsee documentation):

执行此操作
NSExpression *prop1 = [NSExpression expressionForConditional:[NSPredicate predicateWithFormat:@"property1 == nil"] 
                                    trueExpression: [NSExpression expressionForConstantValue: @0] 
                                    falseExpression: [NSExpression expressionForKeyPath:@"property1"]];

(同样适用于property2等)。然后,您可以使用NSExpression格式说明符将这些%@值替换为谓词:

fetch.predicate = [NSPredicate predicateWithFormat:@"%@ + %@ < %@", prop1, prop2, prop3];

CoreData将条件表达式解析为SQLite CASE (...) when 1 then (...) else (...) END子句,该子句在数据库中作为fetch的一部分进行评估:但我不知道将如何与冗长的复合谓词进行比较。 (我也只使用单个条件表达式进行了测试;我假设CoreData可以在一个谓词中处理两个或更多,但留待它确认。)

答案 1 :(得分:0)

NSPredicate *p = [NSPredicate predicateWithFormat:
                  @"(%K==nil AND %K==nil AND %K!=nil AND 0 < %K) OR"
                   "(%K==nil AND %K==nil AND %K!=nil AND %K < 0) OR"
                   "(%K==nil AND %K==nil AND %K!=nil AND %K < 0) OR"

                   "(%K==nil AND %K!=nil AND %K!=nil AND %K < %K) OR"
                   "(%K==nil AND %K!=nil AND %K!=nil AND %K < %K) OR"
                   "(%K==nil AND %K!=nil AND %K!=nil AND (%K + %K) < 0) OR"

                   "(%K!=nil AND %K!=nil AND %K!=nil AND (%K + %K < %K))",

                   @"property1",@"property2",@"property3",@"property3",
                   @"property3",@"property1",@"property2",@"property2",
                   @"property3",@"property2",@"property1",@"property1",

                   @"property1",@"property2",@"property3",@"property2",@"property3",
                   @"property2",@"property1",@"property3",@"property1",@"property3",
                   @"property3",@"property1",@"property2",@"property1",@"property2",

                   @"property1",@"property2",@"property3",@"property1",@"property2",@"property3"
                   ];