views:

353

answers:

3

Hello

I am trying to create a Core Data iPhone application. One of the entities I'm tracking is cars, and one attribute of each car is "manufacturer".

In the "edit car" section of my application, I have a UIPickerView that needs to be loaded with each of the unique manufacturers that have previously been entered into the system. What I'm trying to do is create an NSFetchRequest to get an array of unique "manufacturer" attributes and use that to populate the UIPickerView.

The problem I'm running into is that whether there are zero records or 100 in the data store, there is always one record in the executed fetch request at element zero with a value @"".

Am I doing this wrong or is there an easier way to do this? I wish I could just run a quick sql query!!!

My code is below:

// Populate the manufacturerNameList array
NSManagedObjectContext *moc = [self.selectedLease managedObjectContext];
NSEntityDescription *ed = [NSEntityDescription entityForName:@"Car" inManagedObjectContext:moc];
NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
[fetchRequest setEntity:ed];

// Get only manufacturer and only uniques
[fetchRequest setResultType:NSDictionaryResultType];
[fetchRequest setPropertiesToFetch:[NSArray arrayWithObjects:@"manufacturer",nil]];
[fetchRequest setReturnsDistinctResults:YES];

// Sort by manufacturer in ascending order
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"manufacturer" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];

NSError *error = nil;
self.manufacturerNameList = [moc executeFetchRequest:fetchRequest error:&error];
if (error) {
     // Handle the error
}

NSLog(@"The count of self.propertyNameList is %i",[self.propertyNameList count]);

Thanks!

A: 

The simplest explanation is that you have a car entity that has an empty manufacturer value. When the predicate sorts the fetch, the blank string will be ranked first.

I would log the entire self.propertyNameList and see what you're actually getting back.

TechZen
+1  A: 

manufacturerNameList is going to be an array of Car entities, not manufacturer names. Also, you need to pass an NSArray of NSPropertyDescription objects to setPropertiesToFetch not just attribute names.

Here is how you set the property:

NSDictionary *entityProperties = [ed propertiesByName];
[fetchRequest setPropertiesToFetch:[NSArray arrayWithObjects:[entityProperties objectForKey:@"manufacturer"], nil]];

The results from executeFetchRequest: will be an NSArray of Car entities, so you'll then have to extract the manufacturer attribute values in a loop or something.

You may want to consider creating a Manufacturer entity that your Car entity references, that will allow you to query more in the way you are attempting to right now.

Greg Martin
I get what you're saying completely, and it would surely provide me with more flexibility down the road, but the thing is that Cars are the only entity in the domain, and I'm worried that adding another entity (Manufacturer) to worry about will make the code more complicated overall - given that the only thing I want to do with manufacturers is track them as against the car entity.Given that, would you think that this code is the simplest way to accomplish this?
Simon DeSilva
In that case I think the issue is that you are passing property names and not NSPropertyDescriptions to setPropertiesToFetch and then treat the results as Car entities, not manufacturer strings.
Greg Martin
+1  A: 

Another approach would be to create an entity for manufacturers and have a relationship between Car and Manufacturer such that a Car has one Manufacturer and a Manufacturer has many Cars:

Car <<--> Manufacturer

The Manufacturer entity could have a string attribute its "name".

Then, you could get the full list of manufacturer names by fetching all the Manufacturer objects and looking at the "name" property.

gerry3
Manufacturer should definitely be its own entity with a relationship to car. If you have it as just a property on the Car entity you are limiting your design and going to have more difficulties keeping the manufacturers unique than if you just have it as its own entity.
Marcus S. Zarra