Использование правила каскадного удаления и validateForDelete для отношений «один ко многим» в основных данных iPhone - PullRequest
4 голосов
/ 24 февраля 2010

Предисловие:

У меня есть две сущности, определенные как отношение один-ко-многим: A << -------> B. Отношение B к A называется myAs и является отношением ко-многим с Nullify в качестве правила удаления. , Обратное отношение от А к В является отношением «один к одному» с Каскадом в качестве правила удаления.

Я реализовал validateForDelete для класса B следующим образом:

- (BOOL)validateForDelete:(NSError **)error {
    [super validateForDelete:error];
    BOOL validDelete = FALSE;

    if ([self.myAs count] == 0) {
        validDelete = TRUE;
    }

    return validDelete;
}

Цель этого состоит в том, чтобы удалить объект B, только если с ним больше нет объектов A (но всегда удаляйте объект B, если с ним больше нет объектов A). Этот validateForDelete работает, как и предполагалось, если я проверяю эту проверку вручную перед сохранением: при удалении объекта B:

if ([b validateForDelete:NULL]) {
    //delete b object...
    [context save:&error];
    ...
}

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

Проблема в том, что когда я удаляю объект A, validateForDelete вызывается для объекта B из-за каскада. Я получаю исправленную ошибку: Неразрешенная ошибка (ноль), (ноль), потому что я не вызываю validateForDelete вручную.

Вопрос (ы):

Как получить доступ к вызову validateForDelete из каскадного удаления программным образом, чтобы я мог передать переменную ошибки и / или обработать результат validateForDelete для FALSE?

Если вышесказанное невозможно, как мне поступить с этим вариантом использования? Есть ли еще более практичный способ достижения этого?

Заранее спасибо.

Ответы [ 2 ]

12 голосов
/ 24 февраля 2010

Во-первых, ваш вызов супер игнорирует его ответ и не влияет на ответ супер. Это вообще плохая идея.

Во-вторых, когда вы говорите «НЕТ» validateForDelete, он выдаст исключение, потому что правило удаления не может быть завершено; в этом случае каскад удаляют. Короче говоря, метод validate не является подходящим местом для попыток справиться с этой ситуацией.

Чтобы справиться с этой ситуацией, вы должны переопределить метод -prepareForDeletion в классе A, чтобы он посмотрел на любые B, которые соответствуют этой ситуации, и удалите их соответствующим образом. Вы также захотите изменить правило удаления, чтобы обнулить вместо каскада. Я бы реализовал это следующим образом:

- (void) prepareForDeletion
{
  [super prepareForDeletion];
  if (![self myB]) return; //I don't have a B
  if ([[[self myB] myAs] count] > 1) return; //Has more relationships
  [[self managedObjectContext] deleteObject:[self myB]];
}

Это проверит, есть ли у вас B, и если у вас есть, если у этого B более одного отношения, а если нет, добавьте его в очередь для удаления. В противном случае это позволит Core Data просто аннулировать отношения.

0 голосов
/ 24 февраля 2010

Вы хотите использовать правило удаления "deny". Он предназначен именно для таких ситуаций.

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