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

Получить дату изменения для NSManagedObject в базовых данных?

Вне добавления свойства NSDate к каждому объекту в моем хранилище основных данных существует ли программный способ получить дату изменения для любого объекта?

4b9b3361

Ответ 1

Нет, вы должны добавить дату и управлять ею самостоятельно. Вы можете использовать переопределить -willSave в управляемом объекте для обновления метки времени, но прочитать документацию API для NSManagedObject на -willSave для обновления, не вызывая цикл willSave (документы даже говорят о случае обновления временной метки), В документах также упоминается использование NSManagedObjectContextWillSaveNotification, но это может быть больше проблем при настройке, чем простая проверка, чтобы слишком быстро не устанавливать метку времени.

Ответ 2

Обратите внимание, что это решение предполагает, что у нас есть свойство, называемое dateUpated в модели.

Вместо того, чтобы обрабатывать это на отдельных объектах. Я бы обработал это через уведомление. Документация Apple также предлагает этот способ.

1. Зарегистрируйтесь для уведомления NSManagedObjectContextWillSaveNotification

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(willSaveContext:)         
                                             name:NSManagedObjectContextWillSaveNotification 
                                           object:nil];

2 Установите свойство updateDate в методе наблюдателя для каждого обновленного объекта.

- (void)willSaveContext:(NSNotification *)notification{

    NSManagedObjectContext *context = [notification object];
    NSSet *updatedObject = [context updatedObjects];

    for (NSManagedObject *managedObject in [updatedObject allObjects]) {
        if ([[managedObject.entity propertiesByName] objectForKey:@"dateUpdated"]) {
            [managedObject setValue:[NSDate date] forKey:@"dateUpdated"];
        }

    }

}

Ответ 3

Я лично проверяю, был ли изменен updatedAt, и если да, то я больше его не трогаю. Таким образом, я разбиваю цикл willSave.

- (void)awakeFromInsert {
    [super awakeFromInsert];

    self.primitiveUpdatedAt = [NSDate date];
}

- (void)willSave {
    [super willSave];

    if(![self isDeleted] && self.changedValues[@"updatedAt"] == nil) {
        self.updatedAt = [NSDate date];
    }
}

Ответ 4

Я нашел этот вопрос/вопрос полезным при создании атрибута даты, измененной в Core Data. В этом процессе я пришел к нескольким советам, которые также могут помочь:

(Совет 1: исключение willSave рекурсии)

  • Еще один способ избежать цикла willSave - написать специальную подпрограмму для сохранения контекста, который выполняет итерацию через свои обновленные объекты, которые ищут те, у которых есть свойство dateModified и их настройка. Выполняйте фактические вызовы commitEditing и save после этого цикла. Не беспокойтесь о willSave вообще.

(Совет 2: обновление в реальном времени - но не работает с отменой)

  • Если для отображения даты, измененной пользователю в таблице, вам необходимо обновить дату, вы также можете установить датуModified в вашем случае коммутатора (или что-то еще) для столбца с измененной датой в вашем делетете objectValueForTableColumn delegate ( willDisplayCell для iOS).

  • Там, проверьте, если объект для этой строки isUpdated, и если да, установите dateModified. Я сомневаюсь, что проверка if (obj isUpdated) очень дорогая. Но обязательно сделайте это только для соответствующего столбца, чтобы не повторять его излишне.

  • Возвращает любое строковое представление, которое вы используете для столбца. Чтобы избежать явных различий между временем фактической модификации и установленной датой, укажите только дату, а не время.

  • Это приведет к обновлению dateModified всякий раз, когда пользователь делает выбор таблицы, а также когда таблица перезагружается. Что не идеально - если пользователь изменяет атрибут, который не представлен в таблице, столбец не будет обновляться до тех пор, пока они не сделают выбор. Но он разумно реагирует и намного проще, чем реализация обширной схемы KVO.

  • (Вы все равно хотите установить дату в процедуре сохранения, чтобы уловить изменения, невидимые для таблицы.)

  • UNDO COMPLICATION: К сожалению, диспетчер отмены рассмотрит методы делегирования таблицы change to dateModifed как событие для себя. Впоследствии вызов undo просто отменяет последнее изменение на dateModified - снова и снова. Я попытался преодолеть это, добавив трекер и проверив непустой словарь changeValues, чтобы гарантировать, что dateModified был установлен только один раз перед сохранением. Это работало для отмены удаления, но не для обычных изменений. Таким образом, theres не быстрый способ выполнить живое обновление dateModified pre-save.

Ответ 5

Если кому-то нужен простой способ сделать это в Swift: я написал сообщение в блоге об простом классе UpdateListener для обновления всех updateDate и insertDate. Вы можете найти весь класс в этот смысл. Все, что вам нужно сделать, это вызвать UpdateListener.setupSharedInstance() в методе application(:didFinishLaunchingWithOptions:) вашего делегата приложения.