CoreData проверяет, содержит ли объект отношение ко многим отношениям

У меня есть следующая модель данных в моем приложении:

модель данных

В основном я хочу хранить названия стран, а также названия городов. Каждый город принадлежит одной стране, а одна страна содержит 0 - n городов.

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

До сих пор делаю так:

- (BOOL)countryForName:(NSString *)countryName containsCity:(NSString *)cityName {
    Countries *country = [self countryForName:countryName];
    NSSet *cityNames = [country valueForKey:@"cities"];
    for (Cities *city in cityNames) {
        if ([city.cityName isEqualToString:cityName]) {
            return YES;
        }
    }
    return NO;
}

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

    NSEntityDescription *entity     = [NSEntityDescription entityForName:@"Countries" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor    = [[NSSortDescriptor alloc] initWithKey:@"countryName" ascending:YES];
    NSArray *sortDescriptors            = @[sortDescriptor];
    fetchRequest.sortDescriptors        = sortDescriptors;

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"GetCountryList"];
    aFetchedResultsController.delegate  = self;
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"countryName == %@", countryName];
    [aFetchedResultsController.fetchRequest setPredicate:predicate];

Но как мне это сделать, если в поиске участвуют несколько объектов? Или, другими словами: как добавить уникальные названия городов только для одной страны?
Большое спасибо!


person pmk    schedule 28.05.2013    source источник


Ответы (1)


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

Countries *country = ...
NSString *cityName = ...
if ([[country valueForKeyPath:@"cities.name"] containsObject:cityName]) {
    // ...
}

Или, используя запрос на выборку:

NSString *countryName = ...
NSString *cityName = ...
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Countries"];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"countryName == %@ AND ANY cities.cityName == %@", countryName, cityName];
[fetchRequest setPredicate:predicate];

NSError *error;
NSUInteger count = [self.managedObjectContext countForFetchRequest:fetchRequest error:&error];

if (count == NSNotFound) {
    // error
} else if (count == 0) {
    // no matching country
} else {
    // at least one matching country
}

Обратите внимание, что NSFetchedResultsController обычно используется для отображения содержимого запроса на выборку в виде таблицы, поэтому здесь он не нужен.

person Martin R    schedule 28.05.2013
comment
Привет Мартин, спасибо за этот ответ. Это решение выглядит как очень небольшое улучшение моего кода. Нет ли способа создать запрос на выборку, а затем выполнить countForFetchRequest:, возвращая 0 для страны, не содержащей этот город, или значение › 0 для страны, содержащей этот город? Мне не очень нравится создавать объекты, чтобы уменьшить использование памяти... - person pmk; 28.05.2013
comment
Я только что проверил ваш код, теперь он работает отлично. Я отредактировал код ваших ответов, чтобы другие могли им воспользоваться, большое спасибо :) - person pmk; 28.05.2013
comment
@pmk: Пожалуйста (и да, в коде были глупые ошибки). - Я только что повторно вставил удобный метод fetchRequestWithEntityName (теперь, надеюсь, правильно), который экономит 2 строки кода. - person Martin R; 28.05.2013
comment
Допустим, у вас есть массив cityNames ['CityA', 'CityB', 'CityC']. Как бы вы выбрали страны, которые содержат все города или один из городов в массиве? - person matteok; 02.12.2014