NSPredicate BETWEEN with NSDate reasons - [__ NSDate constantValue]: unrecognized selector sent to instance 0x1e7ff0

I am trying to extract from Core Data records that have startTime between two dates.

Here is my code:

NSDate *today = [NSDate date]; NSDate *distantFuture = [NSDate distantFuture]; // Create the predicate NSPredicate *predicate = [NSPredicate predicateWithFormat:@"startTime BETWEEN %@", [NSArray arrayWithObjects:today, distantFuture, nil]]; NSLog(@"today: %@, distantFuture: %@", today, distantFuture); NSLog(@"predicate: %@", predicate); // Add the predicate to the fetchRequest [[[self fetchedResultsController] fetchRequest] setPredicate:predicate]; NSError *error; if (![[self fetchedResultsController] performFetch:&error]) { // Update to handle the error appropriately. NSLog(@"Unresolved error %@, %@", error, [error userInfo]); exit(-1); // Fail } 

And here is the console output:

 2011-03-11 02:00:03.166 TestApp[2668:307] today: 2011-03-11 01:00:03 AM +0000, distantFuture: 4001-01-01 12:00:00 AM +0000 2011-03-11 02:00:03.174 TestApp[2668:307] predicate: startTime BETWEEN {2011-03-11 01:00:03 AM +0000, 4001-01-01 12:00:00 AM +0000} 2011-03-11 02:00:03.180 TestApp[2668:307] -[__NSDate constantValue]: unrecognized selector sent to instance 0x1e7ff0 2011-03-11 02:00:03.198 TestApp[2668:307] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDate constantValue]: unrecognized selector sent to instance 0x1e7ff0' *** Call stack at first throw: ( 0 CoreFoundation 0x314d0987 __exceptionPreprocess + 114 1 libobjc.A.dylib 0x319a149d objc_exception_throw + 24 2 CoreFoundation 0x314d2133 -[NSObject(NSObject) doesNotRecognizeSelector:] + 102 3 CoreFoundation 0x31479aa9 ___forwarding___ + 508 4 CoreFoundation 0x31479860 _CF_forwarding_prep_0 + 48 5 CoreData 0x352ed973 -[NSSQLSimpleWhereIntermediate _generateSQLBetweenStringInContext:] + 766 6 CoreData 0x35244fff -[NSSQLSimpleWhereIntermediate generateSQLStringInContext:] + 502 7 CoreData 0x35244647 -[NSSQLFetchIntermediate generateSQLStringInContext:] + 74 8 CoreData 0x352e42b3 -[NSSQLGenerator newSQLStatementForFetchRequest:ignoreInheritance:countOnly:nestingLevel:] + 234 9 CoreData 0x352414ab -[NSSQLAdapter _newSelectStatementWithFetchRequest:ignoreInheritance:] + 378 10 CoreData 0x35241329 -[NSSQLAdapter newSelectStatementWithFetchRequest:] + 16 11 CoreData 0x35241205 -[NSSQLCore newRowsForFetchPlan:] + 288 12 CoreData 0x35240531 -[NSSQLCore objectsForFetchRequest:inContext:] + 420 13 CoreData 0x35240151 -[NSSQLCore executeRequest:withContext:error:] + 304 14 CoreData 0x352d0295 -[NSPersistentStoreCoordinator executeRequest:withContext:error:] + 896 15 CoreData 0x3523d877 -[NSManagedObjectContext executeFetchRequest:error:] + 374 16 CoreData 0x352f541b -[NSFetchedResultsController performFetch:] + 766 17 TestApp 0x0001ac6d -[MatchesCalendarDataSource loadMatchesFrom:to:delegate:] + 268 18 TestApp 0x0001ad51 -[MatchesCalendarDataSource presentingDatesFrom:to:delegate:] + 68 19 TestApp 0x00021353 -[KalViewController reloadData] + 110 20 TestApp 0x00021b15 -[KalViewController loadView] + 452 21 UIKit 0x338dc227 -[UIViewController view] + 30 22 UIKit 0x338e8d0b -[UIViewController contentScrollView] + 22 23 UIKit 0x338e8b7b -[UINavigationController _computeAndApplyScrollContentInsetDeltaForViewController:] + 30 24 UIKit 0x338e8a79 -[UINavigationController _layoutViewController:] + 24 25 UIKit 0x338e84d3 -[UINavigationController _startTransition:fromViewController:toViewController:] + 254 26 UIKit 0x338e835f -[UINavigationController _startDeferredTransitionIfNeeded] + 182 27 UIKit 0x338e82a3 -[UINavigationController viewWillLayoutSubviews] + 14 28 UIKit 0x338e823f -[UILayoutContainerView layoutSubviews] + 138 29 UIKit 0x338b10cf -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 26 30 CoreFoundation 0x3146ebbf -[NSObject(NSObject) performSelector:withObject:] + 22 31 QuartzCore 0x30a6c685 -[CALayer layoutSublayers] + 120 32 QuartzCore 0x30a6c43d CALayerLayoutIfNeeded + 184 33 QuartzCore 0x30a6656d _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 212 34 QuartzCore 0x30a66383 _ZN2CA11Transaction6commitEv + 190 35 QuartzCore 0x30a89f9d _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 52 36 CoreFoundation 0x31460c59 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 16 37 CoreFoundation 0x31460acd __CFRunLoopDoObservers + 412 38 CoreFoundation 0x314580cb __CFRunLoopRun + 854 39 CoreFoundation 0x31457c87 CFRunLoopRunSpecific + 230 40 CoreFoundation 0x31457b8f CFRunLoopRunInMode + 58 41 GraphicsServices 0x35d664ab GSEventRunModal + 114 42 GraphicsServices 0x35d66557 GSEventRun + 62 43 UIKit 0x338d5329 -[UIApplication _run] + 412 44 UIKit 0x338d2e93 UIApplicationMain + 670 45 TestApp 0x000029d7 main + 70 46 TestApp 0x00002958 start + 52 ) terminate called after throwing an instance of 'NSException' 

I also tried the predicate below, which uses> = AND <= instead of the BETWEEN operator (see below). This does not cause errors, but also does not bring any records!

 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(startTime >= %@) AND (startTime <= %@)", today, distantFuture]; 

As a test, I tried a predicate that does not include NSDate objects, and it works fine (see below):

 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"location.title == %@", @"Boston"]; 

Any help or advice would be greatly appreciated.

Thanks a lot, Matthew


Edit

Thanks for your help Dave.

So, now I'm back to using the <= construct, but I get 0 objects.

I just used today and distantFuture as a test to absolutely make sure my startTime would be between these dates. In real code, this is a range from fromDate to toDate .

Here is my NSPredicate:

 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"( ( %@ <= %K ) && ( %K <= %@ ) )", fromDate, @"startTime", @"startTime", toDate]; 

Here's the console output:

 predicate: CAST(336261600.000000, "NSDate") <= startTime AND startTime <= CAST(339285599.000000, "NSDate") [sectionInfo numberOfObjects]: 0 

The following are the dates indicated in Core Data (Attribute Type: Date):

 startTime --------- 337249800 337309200 337318200 

I do not know why 0 objects are returned. Can anyone see where I'm wrong?

+7
source share
2 answers

Perhaps try using AND instead of && (although your console output seems to show the correctness of its conversion.

I just posted an example that works for me, note that my state is reversed like this:

@ "(% K> =% @) AND (% K <=% @)"

Here is a complete example

+4
source

According to the documentation, the BETWEEN statement is considered an aggregate expression and ...

Aggregate expressions are not supported by Core Data.

So yes, in order to get around this, you should use the >= and <= constructs.

However, given that one of your dates is [NSDate distantFuture] , you do not need to compare less. You must be able to:

 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"startTime >= %@", [NSDate date]]; 
+24
source

All Articles