Search code examples
objective-ccore-dataios5nullnsfetchrequest

Core Data. Consequent fetch on same object returns null


I have this basic one-to-many relationship in Core Data:

  • Brand has N Products
  • Product has 1 Brand (Inverse relationship to the previous)

And I am parsing products coming from a WS. When a product comes, I need to add it's brand to the newly created product.

For doing so, I need to fetch the Brand and assign it to the Product.

+ (Brand *) getBrandWithId : (int) brand {
    NSManagedObjectContext * context = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Brand" inManagedObjectContext:context];
    [fetchRequest setEntity:entity];
    [fetchRequest setIncludesSubentities:YES];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"id == %@", [[NSNumber numberWithInt:brand]description]];
    [fetchRequest setPredicate:predicate];

    NSError *error = nil;
    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
    for (Brand * brand in fetchedObjects) {
        return brand;
    }
    return nil;
}

As one product is coming next to the other, this function is being called consequently several times for the same Brand (same id).

The behavior is like this:

  • First time being called, the Brand is fetched correctly and returned by this function.
  • Second time (and following times), for the same previous Brand, the function is returning nil.

Does anyone notice what am I doing wrong?


Solution

  • NSError *error = nil;
    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
    for (Brand * brand in fetchedObjects) {
        return brand;
    }
    

    This code seems odd. First, you're passing in an NSError**, but ignoring whatever error might be returned there. Since you seem to be having some trouble with your fetch, it'd make sense to check that.

    Second, the for loop seems misleading. Since the body contains a return statement, you can never execute the loop more than once. While there's no practical difference, it seems like a better indication of the intent here would be something like:

    if (fetchedObjects != nil) {
        return [fetchedObjects objectAtIndex:0];
    }