Как автоматически установить вычисляемое свойство NSManagedObject перед его сохранением? - PullRequest
2 голосов
/ 18 ноября 2011

Скажем, у меня есть NSManagedObject подкласс с именем Item. Всякий раз, когда экземпляр item сохраняется, я хочу обновить свойство на основе вычисленного значения из переходного свойства. Я знаю, что могу обновлять свойство всякий раз, когда изменяется временное свойство, но для этого вопроса предположим, что есть веская причина, по которой я не хочу этого делать.

Я попытался сделать это в методе willSave следующим образом:

- (void)willSave
{
    self.computedProperty = [self computedValueFromTransientProperty];
}

Это вызывает сбой при сохранении контекста. Если я перемещу код из willSave и установлю свойство явно перед вызовом сохранения, он будет работать нормально. В документации Apple говорится, что вам следует избегать изменения свойств управляемого объекта в willSave.

ВОПРОС: есть ли хороший способ встроить функциональность в подкласс NSManagedObject, чтобы свойство можно было обновлять непосредственно перед сохранением без необходимости явного задания свойства вне класса и без установки свойства каждый раз изменение переходного свойства?

1 Ответ

7 голосов
/ 18 ноября 2011

Вы можете установить постоянные свойства из willSave, вам просто нужно быть более осторожным с этим.

Из willSave документов:

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

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

Итак, что происходит, вы меняете computedProperty, что вызывает willSave кбыть вызванным снова, что изменит computedProperty, что вызовет willSave снова, до тех пор, пока ваша программа не выйдет из строя.

Чтобы это исправить, вам нужно проверить, нужно ли снова установить computedProperty:

- (void)willSave
{
    id computed = [self computedValueFromTransientProperty];
    if (![self.computedProperty isEqual:computed])
    {
        self.computedProperty = computed;
    }
}

Это будет означать, что computedValueFromTransientProperty будет вызываться дважды, поэтому вы можете не делать этого, если метод требует больших вычислительных затрат.

Другой вариант - использовать метод набора примитивов, который будет означатьwillSave не будет вызываться дважды, но может иметь побочные эффекты в зависимости от того, как ваше приложение взаимодействует с базовыми данными:

- (void)willSave
{
    self.primitiveComputedProperty = [self computedValueFromTransientProperty];
}
...