Основные данные iPhone: каскадное удаление между отношениями «многие к одному» - PullRequest
21 голосов
/ 05 февраля 2010

У меня есть два класса A и B с отношением многие-к-одному от A до B (несколько объектов A могут ссылаться на один и тот же B). Вопрос заключается в том, что если правило удаления на стороне A является каскадным, будет ли B удалено только при удалении last , ссылающегося на A, или оно будет удалено в первый раз, когда связанный A удален Правило удаления для стороны B отношения - Nullify, если это имеет значение.

Кроме того, я прочитал в документации по основным данным, что в некоторых случаях имеет значение флаг Optional. Но не было ясно, как отношения, которые они иллюстрировали, имели отношение к моему делу. Они говорили о случае сдерживания (B принадлежит A), тогда как в моем случае речь идет о подписке / ассоциации (B относится к A).

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

Есть предложения?

Ответы [ 2 ]

15 голосов
/ 04 декабря 2012

У меня была та же цель, что и у вас (удалить B , как только удалится последняя ссылка A ). Мне потребовалось больше времени, чем ожидалось, чтобы получить это право. Особенно потому что

  • В то время, когда A готовится к удалению, отношение ко многим в B может быть еще не обновлено, поэтому вы не можете просто сосчитать A ссылка в B .
  • isDeleted on A , кажется, уже установлен во время -prepareForDeletion

Вот что сработало для меня, если кому-то интересно (я буду использовать Отдел <- >> Сотрудник , потому что его легче читать):

В Сотрудник :

- (void)prepareForDeletion {
    // Delete our department if we we're the last employee associated with it.
    Department *department = self.department;
    if (department && (department.isDeleted == NO)) {
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isDeleted == NO"];
        NSSet *employees = [department.employees filteredSetUsingPredicate:predicate];

        if ([employees count] == 0) {           
            [self.managedObjectContext deleteObject:department];
        } 
    }
}

Другие люди предложили поместить эту логику в -willSave в Отдел . Я предпочитаю решение, описанное выше, так как в некоторых случаях я действительно хочу сохранить пустой отдел (например, во время переноса хранилища вручную или импорта данных).

0 голосов
/ 08 октября 2017

Вот вариант ответа Лукаса Swift 4 :

public override func prepareForDeletion() {
    guard let department = department else { return }

    if department.employees.filter({ !$0.isDeleted }).isEmpty {
        managedObjectContext?.delete(department)
    }
}
...