Основные данные: как проверить наличие связи «многие ко многим» - PullRequest
2 голосов
/ 10 сентября 2009

У меня есть сущность «Песня» и сущность «Тэг», и между ними есть отношения многие ко многим. Композиция может иметь несколько тегов, а тег может применяться к нескольким композициям.

Я хочу проверить, связан ли с песней определенный тег. Если с композицией связан тег, я хочу показать галочку в табличном представлении.

Для аналогичной логики в примере кода Apple "TaggedLocations" выполняется следующая проверка для проверки наличия связи.

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

Это может быть неэффективно, если в базе данных много тегов, поскольку они будут извлекать все из них в память. Пожалуйста, поправьте меня, если я ошибаюсь.

Есть ли более эффективный способ проверить, связана ли песня с определенным тегом, вместо проверки в Song.Tags?

Ответы [ 2 ]

5 голосов
/ 04 октября 2009

Это на самом деле довольно легко сделать, если полностью без документов. Вы хотите создать запрос на выборку с предикатом, у которого есть операция set. Если мы представим, что ваша модель Tag имеет свойство tagValue, предикат, который вас интересует, это «ANY tags.tagValue == 'footag'"

NSString *tagSearch = @"footag";

// However you get your NSManagedObjectContext.  If you use template code, it's 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];
3 голосов
/ 10 сентября 2009

Вы правы, используя этот код, вы получите весь набор, и сравнение объектов может быть довольно сложным, в зависимости от того, сколько свойств и отношений являются частью объекта объекта.

Во всяком случае, вы не можете избежать набора сравнения для включения. Вероятно, лучшее, что вы можете сделать, это избежать выборки всех свойств / отношений, попросив Базовые Данные получать только объекты NSManagedObjectID.

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

NSManagedObjectID объекты гарантированно являются уникальными, поэтому вы можете безопасно использовать их для проверки на включение набора. Это должно быть гораздо более эффективным с точки зрения производительности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...