iphone - Obtener la fecha de modificación para NSManagedObject en Core Data?
ios core-data (5)
Aparte de agregar una propiedad de NSDate a cada entidad en mi almacén de datos centrales, ¿hay alguna manera programática de obtener la fecha de modificación para cualquier objeto?
No, debes agregar una fecha y administrarla tú mismo. Puede usar override -willSave
en su objeto administrado para actualizar la marca de tiempo, pero lea la documentación de la API para NSManagedObject en -willSave
para -willSave
cómo actualizar sin causar un bucle willSave (los documentos incluso hablan sobre el caso de actualizar una marca de tiempo). Los documentos también mencionan el uso de NSManagedObjectContextWillSaveNotification
, pero puede ser más difícil configurarlo que una simple comprobación para no establecer la marca de tiempo demasiado rápido.
Encontré esta Q / A útil para comenzar a configurar un atributo para la fecha modificada en Core Data. En el proceso, llegué a un par de consejos que también podrían ayudar:
(Consejo 1: evitar willSave recursividad)
- Otra forma de evitar un bucle willSave es escribir una rutina personalizada para guardar el contexto que itera a través de sus objects actualizados buscando aquellos que tienen una propiedad dateModified y configurándola.
commitEditing
las llamadas reales acommitEditing
ysave
después de ese ciclo. No te molestes con willSave en absoluto.
(Consejo 2: actualización en vivo, pero no funcionará con deshacer)
Si necesita una actualización en tiempo real para mostrar la fecha modificada al usuario en una tabla, también puede establecer la fecha modificada en su switch-case (o lo que sea) para la columna con fecha modificada en su método delegado objectValueForTableColumn (willDisplayCell para iOS).
Allí, prueba si el objeto para esa fila está actualizado y, si es así, configura la fecha modificada. Dudo que el cheque
if (obj isUpdated)
sea muy costoso. Pero asegúrese de hacer esto solo para la columna relevante para no repetirla innecesariamente.Devuelve la representación de cadena que está utilizando para la columna. Para evitar disparidades obvias entre el momento de la modificación real y la fecha establecida, muestre solo la fecha, no la hora.
Esto hará que dateModified se actualice cada vez que el usuario haga una selección de tabla, así como cuando la tabla se vuelva a cargar. Lo cual no es perfecto: si el usuario modifica un atributo que no está representado en la tabla, la columna no se actualizará hasta que realice una selección. Pero es razonablemente sensible y mucho más fácil que implementar un amplio esquema de KVO.
(Aún querrá establecer la fecha en la rutina de guardado, para detectar modificaciones que son invisibles para la tabla).
DESHACERSE DE LA COMPLICACIÓN: Desafortunadamente, el administrador de deshacer considerará el cambio del método de delegado de la tabla a dateModifed como un evento en sí mismo. Posteriormente, deshacer llamadas simplemente deshace el último cambio a dateModified - una y otra vez. Intenté superar esto agregando un rastreador y un cheque para un diccionario de Values cambiado no vacío para asegurarme de que la fecha modificada se configuró solo una vez antes de guardarla. Eso funcionó para deshacer eliminaciones, pero no para ediciones regulares. Por lo tanto, no hay una forma rápida de realizar la actualización en vivo de la fecha de guardado anticipado modificado.
Tenga en cuenta que esta solución supone que tenemos una propiedad llamada dateUpated en el modelo.
En lugar de manejar esto en objetos individuales. Me encargaría de esto a través de una notificación. La documentación de Apple también sugiere esta forma también.
1. Registrarse para la notificación NSManagedObjectContextWillSaveNotification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(willSaveContext:)
name:NSManagedObjectContextWillSaveNotification
object:nil];
2 Establezca la propiedad para fecha actualizada en el método de observador para cada objeto actualizado.
- (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"];
}
}
}
Si alguien quiere una manera fácil de hacer esto en Swift: escribí una publicación en el blog sobre una clase UpdateListener
simple para actualizar todas las propiedades updateDate
e insertDate
. Puedes encontrar toda la clase en esta esencia . Todo lo que tiene que hacer es llamar a UpdateListener.setupSharedInstance()
en el método application(:didFinishLaunchingWithOptions:)
de su aplicación delegada.
Personalmente updatedAt
si se modificó, y si es así, ya no lo toco. De esta manera rompo el bucle willSave
.
- (void)awakeFromInsert {
[super awakeFromInsert];
self.primitiveUpdatedAt = [NSDate date];
}
- (void)willSave {
[super willSave];
if(![self isDeleted] && self.changedValues[@"updatedAt"] == nil) {
self.updatedAt = [NSDate date];
}
}