Подтвердить что ты не робот

Основные данные iPhone: каскадное удаление по принципу "много-к-одному"

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

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

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

Любые предложения?

4b9b3361

Ответ 1

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

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

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

В Employee:

- (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 в Отдел. Я предпочитаю решение выше, поскольку в некоторых случаях я мог бы хотеть сохранить пустой отдел (например, во время миграции хранилища вручную или импорта данных).

Ответ 2

Здесь версия Swift 4 ответа Лукаса:

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

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