2015-11-04 10 views
9

Ho visto molte domande sull'eliminazione batch nei dati principali, ma nessuno sembra risolvere il problema.Dati principali NSBatchDeleteRequest sembra lasciare gli oggetti nel contesto

Sto creando un'app iOS 9/Swift utilizzando i dati principali. Al WWDC di quest'anno, ho partecipato alla sessione di Core Data e ho visto che potevo utilizzare NSBatchDeleteRequest per eliminare un numero elevato di oggetti direttamente dall'archivio permanente. Questo funziona per me per alcuni oggetti ma non per altri, e penso che abbia qualcosa a che fare con le mie relazioni.

Ho un oggetto grafico costituito da Subject e Course, in cui esiste una relazione uno-a-molti. I soggetti possono possedere tutti i corsi che desiderano.

v'è una relazione 'corsi' su Subject con una regola di eliminazione di Cascade, come voglio tutti i corsi associati a un subject da eliminare quando un subject è soppresso.

L'inverso è 'oggetto' su Course, con una regola di eliminazione di Nullify. Ecco, io sono un po 'confuso da descrizione di Apple Nullify:

rimuovere la relazione tra gli oggetti, ma non eliminare né oggetto. Questo ha senso solo se la relazione di reparto per un dipendente è facoltativa o se si assicura di impostare un nuovo reparto per ciascuno dei dipendenti prima della successiva operazione di salvataggio.

Ciò rende abbastanza chiaro, ma perché le relazioni dovrebbero essere eliminate ma non entrambi gli oggetti? Se elimino un Course, vorrei che la Course da eliminare e la relazione dal subject alla course da eliminare in modo che un guasto al eliminata Course non apparirà nella NSSet su courses Set Subject s'.

Desidero fornire un modo per eliminare tutti gli oggetti di un'entità. Quando provo questo individualmente recuperando ed eliminando ogni course, courses vengono correttamente cancellati e rimossi dal NSSet di courses su un Subject.

Dato che non ho idea di quanti courses siano presenti e voglio garantire prestazioni elevate in ogni situazione, ho pensato che avrei usato la cancellazione batch per cancellare tutto courses. Il problema è che mentre l'utilizzo di NSBatchDeleteRequest per eliminare tutto Subjects funziona correttamente, eliminando tutto il courses lungo la strada (a causa della regola Cascade), provare a eliminare tutto Courses utilizzando questo metodo sembra lasciare tutti gli oggetti sul posto.

ho usato NSBatchDeleteRequest per eliminare tutti Courses, ma poi quando interrogo il MOC per vedere cosa Subjects e Courses esistono ancora, sia Courses sono ancora restituiti e la Subject possederle ha ancora dei riferimenti ad esse.

Al contrario, quando vado a prendere e cancellare ogni Course singolarmente, la mia successiva prendere visualizza correttamente un array vuoto per tutti Courses e il rapporto 'corsi' sul Subject sembra essere stato adeguatamente modificato.

Sì, sto salvando il contesto dopo aver eseguito la richiesta. Suppongo che il contesto non possa essere informato di ciò che fa il negozio, ma poi di nuovo cancellare tutto il subjects ha funzionato alla grande. Che cosa sta succedendo qui?

+0

Le eliminazioni batch ignorano le regole di eliminazione. https://stackoverflow.com/questions/32915874/can-i-use-nsbatchdeleterequest-on-entities-with-relationships-that-have-delete-r/46073965#46073965 – LShi

risposta

24

Al the WWDC 2015 session which describes NSBatchDeleteRequest è stato spiegato che "Le modifiche non si riflettono nel contesto". Quindi quello che stai vedendo è normale. Gli aggiornamenti batch funzionano direttamente sul file di archivio persistente invece di passare attraverso il contesto dell'oggetto gestito, quindi il contesto non li conosce. Quando elimini gli oggetti recuperandoli e cancellandoli, stai lavorando nel contesto, in modo che sappia quali sono le modifiche che stai apportando (in effetti sta eseguendo tali modifiche per te).

Se si utilizza NSBatchDeleteResultTypeObjectIDs, è possibile unire i risultati dell'eliminazione batch nel proprio contesto utilizzando mergeChangesFromRemoteContextSave:intoContexts: per aggiornare i propri contesti. Probabilmente potresti anche usare reset, se non hai caricato nessun altro oggetto gestito dal contesto.

+0

Grazie! Ho usato reset e ha funzionato. Prima di vedere la tua risposta, ho visto che i corsi mancavano dal database SQLite e l'app rifletteva su questo rilancio. –

+0

Vorrei passare al metodo mergeChanges per sicurezza. Ho una copia del risultato dell'eliminazione batch che ho impostato per tornare come "NSBatchDeleteResultTypeObjectID". Che cosa passo per 'changeNotificationData: [NSObject: AnyObject]' su 'mergeChangesFromRemoteContextSave'? –

+0

Ok, invece di usare 'NSBatchDeleteResultTypeObjectID', mi sono registrato per' NSManagedObjectContextDidSaveNotification' e ho chiamato 'mergeChangesFromRemoteContextSave' dal blocco. –

2

Ho finito per aggiungere quanto segue per occuparmi del contesto dopo l'eliminazione del batch.

[self.managedObjectContext refreshAllObjects]; 
Problemi correlati