Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSPredicate Returns No Results with Fetch Request, Works with Array Filtering

My situation is simple: I have some records in my core data store. One of their attributes is a string called "localId". There's a point where I'd like to find the record with a particular localId value. The obvious way to do this is with an NSFetchRequest and an NSPredicate. However, when I set this up, the request returns zero records.

If, however, I use the fetch request without the predicate, returning all records, and just loop over them looking for the target localId value, I do find the record I'm looking for. In other words, the record is there, but the fetch request can't find it.

My other methods in which I use fetch requests and predicates are all working as expected. I don't know why this one is failing.

I want to do this:

- (void)deleteResultWithLocalID:(NSString *)localId {
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:[NSEntityDescription entityForName:@"WCAAssessmentResult" inManagedObjectContext:context]];
    [request setPredicate:[NSPredicate predicateWithFormat:@"localId == %@", localId]];
    NSError *error = nil;
    NSArray *results = [context executeFetchRequest:request error:&error];
    NSAssert(error == nil, ([NSString stringWithFormat:@"Error: %@", error]));
    if ([results count]) [context deleteObject:[results objectAtIndex:0]];
    else NSLog(@"could not find record with localID %@", localId);
    [self saveContext];
}

But I end up having to do this:

- (void)deleteResultWithLocalID:(NSString *)localId {
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:[NSEntityDescription entityForName:@"WCAAssessmentResult" inManagedObjectContext:context]];
    NSError *error = nil;
    NSArray *results = [context executeFetchRequest:request error:&error];
    NSAssert(error == nil, ([NSString stringWithFormat:@"Error: %@", error]));
    for (WCAAssessmentResult *result in results) {
        if ([result.localId isEqualToString:localId]) {
            NSLog(@"result found, deleted");
            [context deleteObject:result];
        }
    }
    [self saveContext];
}

Any clues as to what could be going wrong?

edit

I've found that I can use the predicate I'm creating to get the results I expect after the fetch request has been executed. So, the following also works:

- (WCAChecklistItem *)checklistItemWithId:(NSNumber *)itemId {
     NSFetchRequest *request = [[NSFetchRequest alloc] init];
     [request setEntity:[NSEntityDescription entityForName:@"WCAChecklistItem" inManagedObjectContext:context]];
     NSArray *foundRecords = [context executeFetchRequest:request error:nil];
     foundRecords = [foundRecords filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"serverId == %@", itemId]];
     if ([foundRecords count]) {
         return [foundRecords objectAtIndex:0];
     } else {
         NSLog(@"can't find checklist item with id %@", itemId);
         return nil;
    }
}

UPDATE

I've come across someone else experiencing this very issue:

http://markmail.org/message/7zbcxlaqcgtttqo4

He hasn't found a solution either.

Blimey! I'm stumped.

Thanks!

like image 479
CharlieMezak Avatar asked Mar 23 '11 13:03

CharlieMezak


2 Answers

If localId is a numerical value, then you should use an NSNumber object in the predicate formation instead of an NSString.

[request setPredicate:[NSPredicate predicateWithFormat:@"localId == %@", 
    [NSNumber numberWithString:localId]]];

NSPredicate format strings automatically quote NSString objects.

like image 153
codelark Avatar answered Nov 15 '22 05:11

codelark


Hate to say it but the most common cause of these types of problems is simple typos. Make sure that your attribute names and the predicate are the same. Make sure that your property names and the attributes names are the same. If a reference to a property works but a reference to attribute name doesn't there is probably a mismatch.

You could test for the latter by comparing the return of:

[result valueForKey:@"localID"]

... with the return of:

result.localID
like image 30
TechZen Avatar answered Nov 15 '22 04:11

TechZen