Core Data fetching many-to-one relationship objects - ios

In my app I have two entities which are Items and Lists. Each item belongs to only one list and each list has many items. Thus in the modal the entities has the following relationships:
For Items: to-one relationship (belongs_to_list) pointing to one list
For Lists: to-many relationship (has_items) pointing to many items
How can I fetch the items using a predicate to check whether the list it's related to is equal to a specific list I provide? I don't want to fetch the items through the list (like fetching objects of has_items). I want to be able to use belongs_to_list in a predicate to compare it to a managed object I have. I tried the following but it's not working. Any help please?
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Items" inManagedObjectContext:_managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"item_detail" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"list.list_name == %#", [self.currentList valueForKey:#"list_name"]];
[fetchRequest setPredicate:predicate];

If I understood well your question, the following predicates would be correct:
[NSPredicate predicateWithFormat:#"belongs_to_list == %#", [self currentList]];
Let me know if this does work for you.

Related

to-many relation as sectionNameKeyPath

I want to show Project such that it shows all the projects on the basis of sharedToUsers basis. Means section name with User.user_id and it should shows all the shared project with that user. but i am not able to set section value for NSFetchedResultsController properly because it is a too many relation and it is crashing on sectionNameKeyPath .
Any Help
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *theParent = [NSEntityDescription entityForName:#"Project" inManagedObjectContext:_managedObjectContext];
//the name key exsit in parent entity of project.
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:10];
[fetchRequest setEntity:theParent];
[fetchRequest setPredicate:_predicate];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:_managedObjectContext sectionNameKeyPath:#"ANY sharedToUsers.user_id"
cacheName:[self getCacheNameForNSFetchedResultsController]];
if you have a senario like i have then when ever you change data in the core data then try donot use to add or update relation ship items using object of parent or category object. if you had to link some thing with category then try to link from child object.
donot use this
[category addRelationShipItem:child];
use this
`[child addToCategory:category];`
when you use this then it will not triger update call in NSFetchResultController call.
Happy coding.
Hi If you want fetch the Project shared by a user you need this predicate:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *theParent = [NSEntityDescription entityForName:#"Project" inManagedObjectContext:_managedObjectContext];
NSString *userId; // If you user_id is a NSNumber change you to it.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY sharedToUsers.user_id = %#",userId];
[fetchRequest setPredicate:predicate];
Last things you are using a NSSort: name , but name it's not a Project property.

Populating a tableview with child objects of parent entity

I have two tableviewcontrollers in a navigation controller hierarchy. The first contains parent entities, which I have successfully populated from a core data entity fetch request. I created a one-to-many relationship in the parent entity to the child entity and seem to be adding child entities okay. I can populate it with all the children of all the parents, but can't restrict it to the current parent. I have tried using predicates in the child tableview controller fetch request but without success.
Should I be using includesSubEntities and keeping the parent entity used in the request? If so, would I use the delegate protocol in some way?
The code below is for the child tableview. The commented-out bits are different attempts!
Thanks.
- (NSFetchedResultsController *)fetchSerials
{
if ( !_fetchSerials )
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity =
[NSEntityDescription entityForName:#"Serial"
inManagedObjectContext:AppDelegatePtr.managedObjectContext];
// NSPredicate *predicate = [NSPredicate predicateWithFormat:#"inExercise.name = '%#'", [[SMNetworkModel sharedInstance] selectedNarrative]];
// [fetchRequest setPredicate:predicate];
// [fetchRequest setRelationshipKeyPathsForPrefetching:#[#"inExercise"]];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"narrative" ascending:YES];
[fetchRequest setSortDescriptors:#[sortDescriptor]];
_fetchSerials = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:AppDelegatePtr.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
_fetchSerials.delegate = self;
NSError *error;
if ( ![_fetchSerials performFetch:&error] )
NSLog(#"fetch error: %#", error.localizedDescription);
}
return _fetchSerials;
}
A stupid typo combined with a shortfall in my understanding of my new friend Core Data was all that was stopping Predicates from working.
I had mistakenly thought you passed objectIds around instead of the objects themselves.
Uncomment the two lines involving the predicate and change the selectedNarrative to the correct property and it all worked!

Filter NSFetchedResultsController to get only objects with some relationship

I have two entities, A and B, and the following relationships:
A -> B - To many
B -> A - To one
In other words: A can have zero or more B and B can have only one A.
I want to use NSFetchedResultsController to show my A entries in a table view, but i want to filter the results by A -> B relationship.
To do so, i have a UISegmentedControl, if the user taps the first segment i want to show only the A entries that have at least one relationship with B, and if the second segment is tapped i want to show only the entries with no relationships with B.
I'm using CoreData's NSManagedObject, so my A object has a NSSet property with all B entries in a relationships with A.
This is how i'm instantiating my NSFetchedResultsController:
NSManagedObjectContext *context = self.managedObjectContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:"A" inManagedObjectContext:self.managedObjectContext];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:descriptorKey ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setEntity:entity];
NSFetchedResultsController *controller = [[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:context
sectionNameKeyPath:controllerKey
cacheName:nil];
NSError *error;
BOOL success = [controller performFetch:&error];
if (success) {
return controller;
}
This code get all A entries, how can i make that filter?
You need to add a predicate to your fetch request:
e.g.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"B.#count == 0"];
[fetchRequest setPredicate:predicate];
This will filter As that don't have any related B objects.
As #Abizern mentioned in comments, you need to add a NSPredicate to your NSFetchedResultsController. The predicate would be something like:
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"b == %#", myVarReferenceToB]];
If you only have a unique identifier in B (lets call it identifier) instead of an object reference you could write it as:
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"b.identifier == %#", myVarReferenceToBIdentifier]];
This will produce your filter.
Every time the user changes the segmented control you will need to re-build the fetch or you will need to keep one NSFetchedResultsController around per segment.

NSFetchRequest / NSFetchedResultsController returning single property distinct but sorted using another attribute of the entity

I am using an NSFetchedResultsController to display data in a table. The data store contains lots of rows that have a groupID, and multiple entities can share a groupID.
Each entity has an insertion date property as well.
I would like to get a list of distinct groupID ordered by the insertion date property. The following code works, except it is not sorted by the insertion date property. I assume that since that property is not one of the ones being fetched, it is not available for sorting.
And I am using MagicalRecord as well, fwiw.
Is there a way to use other properties of the entity for sorting but not have them as part of the result? Adding in the insertion date to the fetched properties makes distinct superfluous since the dates are all unique as they are.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"userID like[c] %#", THEUSERUSERID];
NSFetchRequest *fetchRequest = [AnEntity MR_requestAllWithPredicate:predicate];
[fetchRequest setReturnsDistinctResults:YES];
[fetchRequest setResultType:NSDictionaryResultType];
[fetchRequest setPropertiesToFetch:#[#"groupID"]];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"inDate" ascending:NO];
[fetchRequest setSortDescriptors:#[sortDescriptor]];
_frController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[NSManagedObjectContext MR_rootSavingContext] sectionNameKeyPath:nil cacheName:nil];
Chadbag ... I had the same problem. I researched the setPropertiesToFetch and found out it requires an NSArray of NSPropertyDescriptions ... not just the attribute name.
I think if you REMOVE this:
[fetchRequest setPropertiesToFetch:#[#"groupID"]];
and ADD this:
NSDictionary *entityProperties = [entity propertiesByName];
NSPropertyDescription *propDescription = [entityProperties objectForKey:#"groupID"];
NSArray *propArray = [NSArray arrayWithObject:propDescription];
[fetchRequest setPropertiesToFetch:propArray];
That should work for you ... it did for me!

Sort Ordering In Selective Fetching - Core Data

I'm looking to fetch some objects stored in my core data model with an NSPredicate and a NSSortDescriptor:
NSPredicate *predicate = [NSPredicate
predicateWithFormat:#"myObjectList.objectID like %#", objectID];
NSSortDescriptor *sort = [NSSortDescriptor
sortDescriptorWithKey:#"sortKey" ascending:NO];
NSFetchRequest *fetch = [MyObject fetchRequest];
[fetch setPredicate:predicate];
[fetch setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetch setFetchLimit: n];
NSArray *results = [MyObject objectWithFetchRequest:fetch];
return results;
What I'm wondering is if anybody already knows whether given the fetchLimit n:
the sort is applied to all of the entities in myObjectList with matching objectID and the first n are returned in results?
the first n entities with matching objectID are fetched from myObjectList and then this sub group of MyObjects is sorted, most likely resulting in an inaccurate sort?
Basically I'm wondering if I can fetch an ordered set of items without pulling them all out to sort. Looking forward to your responses!

Resources