I have the following code to select the names of staff from a Core Data entity called StaffRecords. I want to select the records Distinctly but this selects all the records. How do I make the result Distinct?
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"StaffRecords"];
[fetchRequest setPropertiesToFetch:#[#"StaffName"]];
[fetchRequest setReturnsDistinctResults:YES];
NSError *error = nil;
self.StaffNames = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
[self.tableView reloadData];
Using setPropertiesToFetch and setReturnsDistinctResults is correct. But, you also need to set resultType to NSDictionaryResultType.
Note that at the time of writing propertiesToFetch is documented to be an array of NSPropertyDescription instances, but an array of strings of the key names does also work.
Related
I'm new to Core Data and trying to do the following thing:
I want to fetch all the objects in the persistent store and group by an attribute called day. Meanwhile, all the objects should be sorted by an attribute called startTime.
Here is what I do:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Meeting"];
// Add Sort Descriptors
[fetchRequest setSortDescriptors:#[[NSSortDescriptor sortDescriptorWithKey:#"startTime" ascending:YES]]];
NSEntityDescription* entity = [NSEntityDescription entityForName:#"Meeting" inManagedObjectContext:self.managedObjectContext];
NSAttributeDescription* meetingDay = [entity.attributesByName objectForKey:#"day"];
[fetchRequest setPropertiesToFetch:[NSArray arrayWithObjects:meetingDay, nil]];
[fetchRequest setPropertiesToGroupBy:[NSArray arrayWithObject:meetingDay]];
[fetchRequest setResultType:NSDictionaryResultType];
NSError *error = nil;
NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
But for results, what I got is a dictionary, which the key is 'day' and value is the day string.
How can I get all other attributes, basically I mean the whole objects?
Or do I need to fetch all the objects and do the group by myself?
Thanks!
Delete these lines from your fetch code...
[fetchRequest setPropertiesToFetch:[NSArray arrayWithObjects:meetingDay, nil]];
[fetchRequest setResultType:NSDictionaryResultType];
The first limits your data set to one single entity attribute, yet you are wanting the entire entity.
The second specifies an NSDictionary result set, which as far as I understand from your question is unnecessary in this instance. You are seeking an NSArray of entities, not an NSArray containing an NSDictionary of entity attributes.
I have a core data object called Item, it has 2 properties identifier and type
Item
----
identifier
type (A/B)
It is possible to have 2 items with the same identifier but with different type.
I need to fetch all the items with one condition:
if two items has the same identifier, only show the A type.
In other words I want to make sure that the fetched items will have a unique identifier, and in the case of multiple items with the same identifier, priority will be given to item with type A.
I also prefer not to use NSDictionaryResultType if possible
You can fetch from Core Data with a predicate to find (or count) objects with an identifier (btw do NOT use id, it is a reserved word in Cocoa) and you can sort by another property and then you can limit your fetch result to a single item.
That will give you your priority you are looking for. However, I strongly recommend against handling the issue that way and instead writing your creation code to avoid having duplicates in the first place.
Update
What I am saying is that you can't "fetch all the items with one condition...". What you can do is fetch per item (using the identifier), limiting the fetch to a single result sorted by type which will give you your results.
If you wanted all items of type "a", that is doable.
If you wanted all items and filtered on type in a second pass in memory, you could do that
You cannot combine them.
Now, if you want to fetch per item, filtering on the type it would look like this:
NSManagedObjectContext *moc = ...;
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"MyEntity"];
[fetchRequest setFetchLimit:1];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"identifier == %#", myIdentifier];
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"type" ascending:YES];
NSArray *sortArray = [NSArray arrayWithObject:sort];
[fetchRequest setSortDescriptors:sortArray];
NSError *error = nil;
NSArray *results = [moc executeFetchRequest:fetchRequest error:&error];
if (!results) {
NSLog(#"Error: %#\n%#", [error localizedDescription], [error userInfo]);
abort();
}
id mySingleObject = [results lastObject];
NOTE: This code was written in the browser, there are probably errors.
I am pretty new to this and assume I am missing something very simple, I have tried this site and anywhere I could search but found no straightforward answer.
My situation..
My model can have many Calisthenic Entities which can of course contain many sets.
I have a calisthenic detail controller which uses a fetch request to pull all the sets data and display it. With the code below my detail view works fine.
The problem is, if I create and enter another calisthenic detail view my fetch of course pulls all the Set entities from all the calisthenic entities, I of course only want to pull the sets for the calisthenic ID I am interacting with.
So how to I pull all the sets related to 1 calisthenic ID in my fetch request?
- (void)fetchSets
{
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Set"];
NSString *cacheName = [#"Set" stringByAppendingString:#"Cache"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"setNumber" ascending:YES];
[fetchRequest setSortDescriptors:#[sortDescriptor]];
self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:self.calisthenic.managedObjectContext sectionNameKeyPath:nil cacheName:cacheName];
NSError *error;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(#"Fetch failed: %#", error);
}
}
You can use NSPredicate to filter the fetch request based on the parent object which is the Calisthenic.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"calisthenic == %#", calisthenic]
[fetchRequest setPredicate:predicate];
The line above assumes the property of the parent is called calisthenic.
Or if you have created model files (the subclasses of NSManagedObject) for Calisthenic and Sets, you can simply take the parent calisthenic object and get the sets directly.
calisthenic.sets
in which NSSet is returned.
Take a look at the following tutorial on how to generate model files: Getting started with Core Data
my program has a sqlite database with two related tables. One called "Rank" and other one called "Requirement"
I want to fetch all rows from the "Requirement" table that has a relationship with the specific row in a "Rank" table. Following is my code, it grabs the whole table, but I get the specified rows only according to the above mentioned rule.
-(NSArray *) getAllRequirementsForTheRank:(Rank *) rank
{
NSError *error;
NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init]autorelease];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Requirement" inManagedObjectContext:self.context];
[fetchRequest setEntity:entity];
NSPredicate *searchType = [NSPredicate predicateWithFormat:#"Rank = %#", rank];
[fetchRequest setPredicate:searchType];
NSArray *scoutRequirementArray = [self.context executeFetchRequest:fetchRequest error:&error];
for (Requirement *r in scoutRequirementArray)
{
NSLog(#"Requirementttt : %# :", r.requirementName);
}
return scoutRequirementArray;
}
If you have the relationship modelled in core data, just get the linked objects from the relationship property. You don't need another fetch request. rank.requirements will give you an NSSet of everything you need. (I'm assuming names for your object and properties here).
In the FRC documentation, it says that it is intended to efficiently manage the results returned from a Core Data fetch request to provide data for a UITableView object.
I am trying to setup my Core Data stack to handle the storage and retrieval of some VERY basic data. Can I not use FRC? I need to display a value set in the db to a UILabel, what is the best Core Data method to use for that?
I have a core data book I am trying to get through, but the going is rough, so any help here would go a long way. Thanks!!
NSFetchedResultsController may be overkill if all you want is to fetch an object and display one of its attributes in UILabel. Take a look at NSFetchRequest and start with something like this:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:entityDescription
inManagedObjectContext:managedObjectContext]];
NSPredicate *predicate = /* define predicate here */;
[fetchReqest setPredicate:predicate];
NSError *error = nil;
NSArray *results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
If you want to sort your results, read up on NSSortDescriptor. You will need to set sort descriptors prior to -executeFetchRequest: call.
Your results will be in 'results' array - and they should include NSManagedObjects that you can get attribute values from.