12

I have a core data database and I am trying to create a fetch request using a block predicate, but I get an Unknown Predicate error:

NOTE: employeeToHouse is a property of type House that was created for me when I subclassed NSManagedObject

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Place"];
request.predicate       = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
    Place *sortPlace            = (Place *)evaluatedObject;
    CLLocation *placeLocation   = [[CLLocation alloc] initWithLatitude:sortPlace.latitude.doubleValue 
                                                             longitude:sortPlace.longitude.doubleValue];
    CLLocationDistance distance = [placeLocation distanceFromLocation:self.userLocation];
    sortPlace.distanceToUser    = [NSNumber numberWithDouble:distance];
    if(distance<3000)
    {
        return YES;
    }
    return NO;
}];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@ "distanceToUser" 
                                                                                 ascending:YES 
                                                                                  selector:@selector(localizedCaseInsensitiveCompare:)]];

[self.loadingView removeSpinner];
[self setupFetchedResultsControllerWithFetchRequest:request];

I then get this error:

NSInvalidArgumentException', reason: 'Unknown predicate type for predicate: BLOCKPREDICATE(0x70ad750)'

Am I doing something wrong?

lnafziger
  • 25,760
  • 8
  • 60
  • 101
Ilya Lapan
  • 1,103
  • 2
  • 12
  • 31
  • Are you using an "Unknown predicate type"? – Robert Harvey May 04 '12 at 17:30
  • Well, that's what the error message says. – Robert Harvey May 04 '12 at 18:35
  • @C4- Is that how Objective C code is normally formatted? That is hella ugly. – Robert Harvey May 04 '12 at 18:36
  • @Robert it can be, was just trying to use xcode's indentation to make the code not scroll too much, but yeah, this one didn't work so well.. – C4 - Travis May 04 '12 at 18:52
  • This won't help your problem, but you can save the extra code for the cast by using: `^BOOL(Place *evaluatedObject, NSDictionary *bindings) {` – lnafziger May 04 '12 at 20:21
  • 1
    Also, on a completely unrelated note, `distanceFromLocation` has a bug. If you reverse the two locations (like `distance = [self.userLocation distanceFromLocation:placeLocation];`) you will get a different value, even though the distance should be the same no matter which way that you go. The correct value may be obtained by averaging the two distances. – lnafziger May 04 '12 at 20:35
  • I thought it is because CLLocation uses some accuracy info. At least thats what i thought. – Ilya Lapan May 04 '12 at 21:40
  • 4
    I think i figured it out. It took me a while, but it seems (I am not entirely sure) core data doesn't support Block predicate, as they can't be translated to SQLite. Well, seems I need to look for a workaround. – Ilya Lapan May 04 '12 at 22:10
  • Yes--I think Core Data + SQLLite only supports core data predicate language predicates. One workaround is to load all your places, or your places in chunks, then filter/sort them in memory with your block predicate. – nielsbot Jul 15 '12 at 22:37
  • @Ilya Lapan, If this is solved, can you provide an answer and mark it as such? It might save the next person from having to read through these comments. And you might get an up-vote ;) – lindon fox Oct 15 '12 at 06:46

1 Answers1

16

AFAIK you cannot use block predicates with CoreData.

See top voted answer here: NSFetchRequest and predicateWithBlock

The reason being that CoreData cannot translate C-code contained in a block into a SQL query.

Community
  • 1
  • 1
Cocoanetics
  • 8,171
  • 2
  • 30
  • 57