views:

57

answers:

2

I want to get a single object from my Core Data datastore, here is the code I have been using but it returns an array of objects, there must be a simpler and better way:

NSFetchRequest *request= [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Manufacturer" inManagedObjectContext:managedObjectContext];
NSPredicate *predicate =[NSPredicate predicateWithFormat:@"ManufacturerID==%@",[[mitems objectAtIndex:i] objectForKey:@"ManufacturerID"]];
[request setEntity:entity];
[request setPredicate:predicate];

NSError *error;
NSArray *entities = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
+2  A: 

If your predicate always fetches more than one result:

  • refine the predicate - don't forget you can build predicates with logic like AND/OR, simple equality is easy but may not be selective enough in your case.

  • just select the result you want from the array, it's no big deal - although if this is possible it should also be possible to refine the predicate...

  • consider reorganizing your data model so that you can refine the predicate to get just one item back.

The fetch always returns an array, that is its definition. However it can be an array of one object.

Adam Eberbach
well then what I got works perfectly :) Thanks for the clarification, my ManufacturerID will always be unique so I should be all set.
Slee
A: 

It will always return an array but you can make it cleaner:

NSFetchRequest *request= [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Manufacturer" inManagedObjectContext:managedObjectContext];
NSPredicate *predicate =[NSPredicate predicateWithFormat:@"ManufacturerID==%@",[[mitems objectAtIndex:i] objectForKey:@"ManufacturerID"]];
[request setEntity:entity];
[request setPredicate:predicate];

NSError *error;
//Making a mutable copy here makes no sense.  There is never a reason to make this mutable
//NSArray *entities = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
[request release], request = nil;
id manufacturer = [[managedObjectContext executeFetchRequest:request error:&error] lastObject];
NSAssert1(error && !manufacturer, @"Error fetching object: %@\n%@", [error localizedDescription], [error userInfo]);

-lastObject will return the last item in the array or nil if the array is empty. This keeps your code a little cleaner when you know there is going to be one object in the array or if you don't care what object you pull out of the array.

BTW, your property names should start with a lower case letter. I am surprised the compiler did not warn you about that.

Marcus S. Zarra
so instead of mutableCopy when I want all of the elements in the array what should I use instead? Also I only used capitals on property names of the entities in my core data model , otherwise I use lowercase.
Slee
In your code in the question you have `ManufacturerID` hence my comment on that part :) As for your other copy, the `-executeFetchRequest:error:` returns an array. You do not need to do anything else with it. Calling `-mutableCopy` just turns it into a `NSMutableArray` which doesn't do anything useful when you are working with an `NSArray` returned from Core Data. Adding to that array will not add objects to Core Data; removing objects from that array will not remove them from Core Data.
Marcus S. Zarra