NSPredicate for max(arrayOfNSDates)
I got problem with NSPredicate.
I got some engine where the predicates are constructed from a definition coming from a web service.
I use somethning like that:
[NSPredicate predicateWithFormat:@"max({1,2,3})==3"]
it's great, but I need max func开发者_如何学编程tion for NSDate objects. Here http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSExpression_Class/Reference/NSExpression.html#//apple_ref/doc/uid/TP30001190 is wrote that max() function can get only array containings objects representing numbers.
Is there any solution to use this function for that (override some method, create some category for NSPredicate)
Thanks in advance.
OK, this is possible, but it's weird. We'll have to build the format string programmatically. Alternatively, we could built it all by creating the individual NSExpression
objects, but that'd be a lot more code (albeit likely safer, but whatever).
NSDate *maxDate = ...;
NSArray *arrayOfDates = ...; // an NSArray of NSDate objects
NSMutableArray *dateFormats = [NSMutableArray array];
for (NSDate *date in arrayOfDates) {
NSString *format = [NSString stringWithFormat:@"%f", [date timeIntervalSinceReferenceDate]];
[dateFormats addObject:format];
}
NSString *dateFormatString = [dateFormats componentsJoinedByString:@","];
NSString *format = [NSString stringWithFormat:@"CAST(max({%@}) = %%@, 'NSDate')", dateFormatString];
// format now looks like CAST(max({xxxx.xxxx, nnnn.nnnn, aaaa.aaaa, ....}), 'NSDate') = %@
NSPredicate *datePredicate = [NSPredicate predicateWithFormat:format, maxDate];
The trick here is to use the date's absolute time interval since the reference date as the arguments to the max()
function, and then turn the result of that back into a date by using CAST()
. More info on how to use the CAST()
function with dates can be found in this blog post.
This solutions is realy good, but don't solve my problem. I got something like this:
NSPredicate* predicate = [NSPredicate predicateWithFormat: condition];
[predicate evaluateWithObject:nil substitutionVariables: currentForm];
And condition can be:
max($widgetWhichReturnDate.result.result,$widgetWhichReturnDate.result)
or
max($widgetWhichReturnInt.result,$widgetWhichReturnInt1.result)
what widget is used here depends from webservice. So I don't like to use different functions for Date and int (or in the future maybe float, double etc)
精彩评论