I'm trying to design my CoreData model for this situation:
We have Song
object which have to-many relationship with some List
.
Each List
have name
property and also have to-many relationship with Song
These many-to-many relationship is needed because one Song
can be presented in each List
at the same time.
I need to somehow obtain list of Song
s grouped by these headers (name of List
) using NSFetchedResultsController
(since user may have 10,000 songs and I don't want to store it somewhere in NSArray
).
When I try to set sectionNameKeyPath:
with some value, e.g. @"List.name"
I've got an error "to-many relationship is not allowed" and of course this makes sense.
So I need help how to design my model to be able to have Song
s and some List
s like "History" / "Next Playing" etc. and to be able to fetch all the data with NSFetchedResultsController
.
Any help appreciated. If my explanation wasn't clear, please ask additional info.
Part of my code:
- (void)initFetch {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Song"];
[fetchRequest setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"index" ascending:YES]]];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"ANY list.@count != 0"];
fetchRequest.fetchBatchSize = 20;
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.context sectionNameKeyPath:@"name" cacheName:nil];
[self.fetchedResultsController setDelegate:self];
NSError *error = nil;
[self.fetchedResultsController performFetch:&error];
if (error) {
NSLog(@"Unable to perform fetch.");
NSLog(@"%@, %@", error, error.localizedDescription);
}
}
Using FRC can be great for displaying data to your user but in using this it can dictate how your model needs to be structured rather than how you might otherwise feel your model entities and relationships should be structured. In your case it looks like you are wanting to see a list of actual States
for songs in your database rather than a list a of songs. Each state instance would have a one-one relationship to a song and the state could have a one-to-many relationship in your lists eg. be linked to a History list, playNext list, currentlyPlaying "list" (with only one instance in the last case). By setting your FRC entity to this State
entity and section key-path linked to the list that the state is in your could achieve the above requirement without having to manipulate indexPaths or work with multiple FRC's. Also having this separate entity allows you to add other attributes later such as the date this was last played or an aggregate for how times it has been played. All of which could be done on the state entity instead of on the Song entity itself.
You don't need to use an FRC to prevent excessive data loading, it isn't the thing which does that. The power of the FRC is its observation of the context to detect changes. That power also doesn't work well when you're trying to navigate across relationships so you're probably also not going to gain from using an FRC in this case.
What limits your data usage is re-faulting managed objects when you don't need them any more (manually in some cases but the system will do this itself when it needs to) and batching the fetch request. When you set a batch size on the fetch request the returned NSArray
will deal with only loading pages of data at a time into memory. The FRC benefits from this, but doesn't control it - and if you forget to add the batch the FRC won't do it for you!
So, you can either setup a system where you have multiple arrays, 1 per section, and manage everything yourself. Or you could use multiple FRCs, 1 for each section, and manipulate the index paths so everything hangs together.
Or, you could change your data model by adding intermediate objects which represent the membership of a Song
in a List
, because this would break the many-to-many relationships and leave you with a navigable relationship in predates and sort descriptors. In this case the new entity would be the one you were fetching for the FRC. Note the above mentioned issue about change tracking across relationships though, take care with what you change and how...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With