2014-10-10 5 views
9

sto cercando di osservare i singoli NSManagedObject modifiche sulla NSManagedObjectContextWillSaveNotification:HasChanges di NSManagedObject è vero, mentre changedValues ​​è vuoto

- (void)managedObjectContextWillSave:(NSNotification *)notification 
{ 
    for (NSManagedObject * object in self.mutableObservedManagedObjects) 
    { 
     if (object.hasChanges) 
     { 
      [self managedObjectWasUpdated:object]; 
     } 
    } 
} 

Il problema è che hasChanges è vero, mentre object.changedValues è vuota, quindi erroneamente innescando managedObjectWasUpdated: (?).

Sto cercando di capire perché questo è il caso e se dovrei controllare meglio object.changedValues.count prima di chiamare managedObjectWasUpdated:.


isInserted e isDeleted sono entrambi falsi.

risposta

4

Ho riscontrato lo stesso problema. Invece di ottenere le bandiere, ho appena controllato se changedValues ​​() è vuoto.

per SWIFT:

if !managedObject.changedValues().isEmpty { 
    // Has some changed values 
} 
+0

Funziona, ma ancora, questo non è un comportamento documentato e fa meravigliarsi quando Apple lo romperà ... :( –

2

In base al documento, hasChanges restituirà SÌ se il destinatario è stato inserito, è stato cancellato o presenta modifiche non salvate, altrimenti NO.

Nel tuo caso, puoi controllare lo isInserted, isUpdated, isDeleted per trovare cosa è successo al tuo oggetto gestito. changedValues mostra solo le proprietà che sono state modificate dall'ultimo recupero o salvataggio del ricevitore.

+2

Avevo seguito la documentazione e 'isInserted' /' isDeleted' erano entrambi falsi, 'isUpdated' true, eppure no' changedValues'. – Rivera

0

Avete attributi transitori sul entità? Sto vedendo il comportamento che descrivi e ho scritto un codice di prova che mostra che la modifica di un attributo transitorio causa hasChanges per restituire true, mentre changedValues è vuoto.

È possibile evitare questo comportamento utilizzando setPrimitiveValue:forKey: per modificare l'attributo transitorio o il metodo equivalente generato da Core Data (setPrimitiveFoo: per un attributo denominato foo). Potresti anche implementare il setter dell'attributo transitorio per farlo.

6

Nella mia esperienza, se l'entità già esisteva, è stato caricato e poi si imposta un valore a una proprietà che è uguale al suo valore precedente, quindi il record sarà segnato come aggiornato, hasChanges torneranno YES e changedValues sarà vuoto Quando salvi il contesto, ciò che viene aggiornato è una speciale colonna Dati di base chiamata Z_OPT, che si riferisce al numero di volte in cui un'entità è stata aggiornata. Per queste situazioni si può fare qualcosa di simile prima di salvare:

for (NSManagedObject *managedObject in context.updatedObjects.objectEnumerator) { 
    if (!managedObject.changedValues.count) { 
     [context refreshObject:managedObject mergeChanges:NO]; 
    } 
} 

al fine di fare neanche aggiornare il valore Z_OPT.

+0

Credo che questa sia la risposta più precisa. HasChanges è basato su _everything_ che Core Data conosce (incluso Z_OPT). 'changedValues ​​()' sta riportando i campi della tua entità che sono diversi. Nella maggior parte dei casi le applicazioni probabilmente interessano di più a 'changedValues ​​(). isEmpty'. –

+0

Invece di controllare 'changedValues.count' puoi usare una nuova proprietà introdotta su' NSManagedObject': 'var hasPersistentChangedValues: Bool' –

0

Da iOS 7 è anche possibile utilizzare hasPersistentChangedValues ​​anziché valori modificati. Penso che questo si comporti meglio.