7

que tienen un NSManagedObject con dos propiedades:Autoupdating NSManagedObject modificación de la propiedad de marca de tiempo

NSNumber *score; 
NSDate *score_timestamp; 

Quiero mi campo score_timestamp que se actualiza cada vez que actualizo score.

Obviamente no puedo usar el método -willSave ya que mi contexto se guarda ocasionalmente, y score_timestamp no estará actualizado. Por lo tanto, debo anular -setScore: o configurar mi objeto administrado como un observador clave-valor para su propio campo score.

La solución parece fácil -setScore::

- (void) setScore:(NSNumber *)score 
{ 
    [self willChangeValueForKey:@"score"]; 
    [self setPrimitiveScore:score]; 
    [self didChangeValueForKey:@"score"]; 

    self.score_timestamp = [NSDate date]; 
} 

¿Hay advertencias en hacer las cosas de esa manera? O debería usar una solución KVO?

actualización

Hasta ahora he recibido dos respuestas que mi código no funcionará a través setValue: forKey: y todavía estoy esperando por ejemplo. Llamada ingenua al [(NSManagedObject *)myObject setValue:value forKey:@"score"] llama a mi setter de todos modos.

Así que si me cambio a una solución de MVA, debo addObserver: en todas awake métodos y retirarlo en willTurnIntoFault? O eso no es tan simple?

+0

En serio, ambos contestadores que indican que setValue ... no funcionarán son incorrectos. Puede probar esto de manera bastante trivial al poner un punto de interrupción en su acceso, luego cambiar el valor usando setValue. – jrturton

+0

@jrturton Ya lo he probado, seguramente se llama. Pero no soy un experto en Core Data para asegurarme de que haya otra forma de cambiar mi propiedad sin el acceso. Me refiero a la forma de ser utilizado ocasionalmente en código real. – iHunter

+0

No. Todas las llamadas de datos centrales pasarán por su setter (posiblemente a través de setValueForKey primero). Es parte del principio de encapsulación. Podrías tener un acceso directo freaky al ivar pero esto tendría que ser algo que habías escrito tú mismo que probablemente también rompería el contexto del objeto administrado. No te harías eso a ti mismo, ¿verdad? – jrturton

Respuesta

4

La implementación en su pregunta está bien. Cualquier intento de KVC de actualizar su valor también pasará por el método setter (setValue: forKey:) simplemente busca un método de acceso que coincida con setKey, vea here para más detalles).

+2

Veo "No debe anular este método" en la documentación 'NSManagedObject -didChangeValue:'! – iHunter

+0

¡Es un excelente punto! Será mejor que piense en una mejor respuesta ... – jrturton

+0

He editado tu respuesta porque comenzó a tener +1 mientras era peligroso. Gracias por su esfuerzo para ayudarme, para expresar mi gratitud, he + 1ed algunas de sus respuestas a otras preguntas (también son de gran ayuda :) – iHunter

0

En este método, si por algún motivo modifica el objeto no como su subclase personalizada, sino como NSManagedObject utilizando setValue: forKey:, la fecha no se actualizará.

+0

¿Podría darnos un ejemplo? – iHunter

1

Usted está buscando Key-Value Observing

[objectWithArray addObserver:self 
        forKeyPath:@"score" 
        options:NSKeyValueObservingOptionNew 
        context:nil]; 

Luego de observar que:

-(void)observeValueForKeyPath:(NSString *)keyPath 
         ofObject:(id)object 
         change:(NSDictionary *)change 
         context:(void *)context 
{ 
    //Check if [change objectForKey:NSKeyValueChangeNewKey] is equal to "score" 
    //and update the score_timestamp appropriately 
} 

deberá registrarse en la notificación cuando se despierte de traer y anular el registro cuando se culpa, yo creo.

+0

Sí, KVO es una buena solución aquí, pero no veo ningún problema en mi código existente. Sospecho que configurar otra propiedad en setter no es una buena idea, pero quiero saber por qué, porque veo que funciona :) – iHunter

+0

Si puede garantizar que su código solo utilizará el getter/setter generado dinámicamente para esta propiedad, su El código debería funcionar, pero si alguna vez usa setValue: forKey: la marca de tiempo no se actualizará. –

+1

@iHunter - nada de malo en establecer otra propiedad en un setter. No es diferente a configurarlo en cualquier otro código. Si estuviera configurando la propiedad _same_, estaría en problemas, pero ese no es el caso aquí. – jrturton

Cuestiones relacionadas