Основные данные: как проверить наличие связи «многие ко многим»

StackOverflow https://stackoverflow.com/questions/1406565

  •  05-07-2019
  •  | 
  •  

Вопрос

У меня есть "Песня" Сущность и «тег» сущность, и они имеют много-много отношений между ними. Песня может иметь несколько тегов, а тег может быть применен к нескольким песням.

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

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

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

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

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

Это было полезно?

Решение

Это на самом деле довольно легко сделать, если полностью без документов. Вы хотите создать запрос на выборку с предикатом, у которого есть операция set. Если мы представим, что в вашей модели тегов есть свойство 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];

Другие советы

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top