Io lavoro su un app che ha regolarmente per elaborare 100K inserti, eliminazioni e aggiornamenti con Core Data. Se si soffoca sugli inserti 5K, è necessario eseguire un'ottimizzazione.
In primo luogo, creare una sottoclasse NSOperation per l'elaborazione dei dati. Sovrascrivi il suo metodo -main per eseguire l'elaborazione. Questo metodo, tuttavia, non è garantito per l'esecuzione sul thread principale. Infatti, il suo scopo è di evitare l'esecuzione di codice costoso sul thread principale che potrebbe influire sull'esperienza utente facendolo congelare grossolanamente. Quindi, all'interno del metodo -main, è necessario creare un altro contesto dell'oggetto gestito che sia il figlio del contesto dell'oggetto gestito del thread principale.
- (void)main
{
NSManagedObjectContext *ctx = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[ctx setPersistentStoreCoordinator:mainManagedObjectContext.persistentStoreCoordinator];
[ctx setUndoManager:nil];
// Do your insertions here!
NSError *error = nil;
[ctx save:&error];
}
Dato le circostanze, non credo che avete bisogno di un direttore di annullamento. Avere uno incorrerà in una penalità legata alle prestazioni poiché Core Data sta monitorando le tue modifiche.
Utilizzare QUESTO contesto per eseguire tutte le azioni CRUD nel metodo -main, quindi salvare il contesto dell'oggetto gestito. Il contesto dell'oggetto gestito del thread principale deve essere registrato per rispondere a NSNotification denominato NSManagedObjectContextDidSaveNotification. Registrare in questo modo:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mocDidSaveNotification:) name:NSManagedObjectContextDidSaveNotification object:nil];
quindi definire che il selettore:
- (void)mocDidSaveNotification:(NSNotification *)notification
{
NSManagedObjectContext *ctx = [notification object];
if (ctx == mainManagedObjectContext) return;
[mainManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}
Quando tutto questo viene insieme, che vi permetterà di eseguire operazioni di lunga durata su thread in background senza bloccare il thread dell'interfaccia utente. Esistono diverse varianti di questa architettura, ma il tema centrale è questo: l'elaborazione su thread BG, l'unione sul thread principale, l'aggiornamento dell'interfaccia utente. Alcune altre cose da tenere a mente: (1) mantenere un pool di autorelease durante l'elaborazione e scaricarlo ogni tanto per mantenere basso il consumo di memoria. Nel nostro caso, lo facciamo ogni 1000 oggetti. Adatta le tue esigenze, ma tieni presente che il drenaggio può essere costoso a seconda della quantità di memoria richiesta per oggetto, quindi non vuoi farlo troppo spesso. (2) prova a ridurre i tuoi dati al minimo indispensabile per avere un'app funzionale. Riducendo la quantità di dati da analizzare, si riduce la quantità di tempo necessaria per salvarlo. (3) utilizzando questo approccio multithread, è possibile elaborare i dati contemporaneamente. Quindi crea 3-4 istanze della sottoclasse NSOperation, ognuna delle quali elabora solo una parte dei dati in modo che vengano eseguiti simultaneamente, risultando in una minore quantità di tempo reale consumato per l'analisi del set di dati.
Come si è verificato questo problema? Ho a che fare con un set di dati di dimensioni simili se non più grande e ho bisogno di scaricarlo una volta al giorno dal servizio web. Sto prendendo in considerazione il download di un file .sqlite preparato per la notte rispetto al servizio web attuale. – Augie
Penso che il caricamento di un file sqlite pronto per l'uso sia la migliore soluzione possibile per questi casi, o per lo meno semplice. Altre soluzioni sono troppo complesse e le prestazioni sono comunque scadenti sui dispositivi mobili. – Matthes