Objective C NSPredicate 两个属性之和
Objective C NSPredicate sum of two properties
我正在尝试创建一个 NSPredicate,它可以计算两个属性的总和并将其与对象的另一个 属性 进行比较:
对象.属性1 + 对象.属性2 < 对象.属性3
我尝试了 (%K + %K) < %K 但没有成功。
PS:即使某些属性为空也应该工作。
我尽量避免使用大量复合谓词。
谢谢,
弗罗林
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"
];
假设您使用的是 SQLite 持久存储,提取谓词将转换为等效的 SQLite WHERE 子句。因此,NULL 值的处理由 SQLite 决定。来自 SQLite documentation:
Adding anything to null gives null
因此,如果谓词中的任何属性为 NULL,则总和将为 NULL。 Predicate Programming Guide 也明确指出必须单独测试 NULL 值:
A comparison predicate does not match any value with null except null (nil) or the NSNull null value .... If you want to match null values, you must include a specific test in addition to other comparisons ...
因此,正如@Kamil.S 在他的回答中所做的那样,您将不得不在谓词中显式测试空值。有一种方法可以让它更容易阅读和处理:用条件表达式(相当于 property1 == nil ? 0 : property1
)替换 属性 值。您可以使用 NSExpression
(see 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
子句,该子句在数据库中作为提取的一部分进行评估:但我不知道与冗长的复合谓词相比性能如何。 (我也只使用单个条件表达式进行了测试;我假设 CoreData 可以在单个谓词中处理两个或更多个,但留待您确认。)
我正在尝试创建一个 NSPredicate,它可以计算两个属性的总和并将其与对象的另一个 属性 进行比较:
对象.属性1 + 对象.属性2 < 对象.属性3
我尝试了 (%K + %K) < %K 但没有成功。
PS:即使某些属性为空也应该工作。
我尽量避免使用大量复合谓词。
谢谢, 弗罗林
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"
];
假设您使用的是 SQLite 持久存储,提取谓词将转换为等效的 SQLite WHERE 子句。因此,NULL 值的处理由 SQLite 决定。来自 SQLite documentation:
Adding anything to null gives null
因此,如果谓词中的任何属性为 NULL,则总和将为 NULL。 Predicate Programming Guide 也明确指出必须单独测试 NULL 值:
A comparison predicate does not match any value with null except null (nil) or the NSNull null value .... If you want to match null values, you must include a specific test in addition to other comparisons ...
因此,正如@Kamil.S 在他的回答中所做的那样,您将不得不在谓词中显式测试空值。有一种方法可以让它更容易阅读和处理:用条件表达式(相当于 property1 == nil ? 0 : property1
)替换 属性 值。您可以使用 NSExpression
(see 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
子句,该子句在数据库中作为提取的一部分进行评估:但我不知道与冗长的复合谓词相比性能如何。 (我也只使用单个条件表达式进行了测试;我假设 CoreData 可以在单个谓词中处理两个或更多个,但留待您确认。)