Basic data: how to check for many-to-many relationships

I have a "Song" Entity and a "Tag" entity and they have many different relationships between them. A song can have multiple tags, and a tag can be applied to multiple songs.

I want to check if the Song has a specific tag associated with it. If a song has a tag associated with it, I want to show a check mark in the table view.

For similar logic, Apple's "TaggedLocations" sample code performs the following check to see if a relationship exists.

if ([event.tags containsObject:tag]) {
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
}   

      

This can be inefficient if there are many labels in the database, as they will fetch all of them in memory. Please correct me if I am wrong.

Is there a more efficient way to check if a song is associated with a specific tag rather than checking in Song.Tags?

+2


source to share


2 answers


This is actually quite easy to do if not fully documented. You want to create a select query with a predicate that has a given operation. If we assume that your tag model has a tagValue property, the predicate you care about is "ANY tags.tagValue ==" footag ""



NSString *tagSearch = @"footag";

// However you get your NSManagedObjectContext.  If you use template code, it from
// the UIApplicationDelegate
NSManagedObjectContext *context = [delegate managedObjectContext];

// Is there no shortcut for this?  Maybe not, seems to be per context...
NSEntityDescription *songEntity = [NSEntityDescription entityForName:@"Song" inManagedObjectContext:context];

NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:songEntity];

// The request looks for this a group with the supplied name
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagValue == %@", tagSearch];
[request setPredicate:predicate];

NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];

[request release];

      

+5


source


You are correct using this code you will get the whole set and comparing objects can be quite tricky depending on how many properties and relationships are part of the object object.

Anyway, you cannot escape the set comparison for inclusion. Probably the best thing you can do is not fetch all properties / relationships, querying Core Data just to get NSManagedObjectID objects.



NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Tag" inManagedObjectContext:[self managedObjectContext]]]; 
[fetchRequest setResultType:NSManagedObjectIDResultType];

      

NSManagedObjectIDs are guaranteed to be unique, so you can safely use them to check whether an inclusion is enabled. It should be much more efficient for a performance perspective.

+3


source







All Articles