2014-12-06 12 views
6

Eseguo il mio programma che crea contenuto di dati di base che viene visualizzato in un NSOutlineView utilizzando NSTreeController. La seconda volta che eseguo il programma, desidero pulire il contenuto del mio NSTreeController ed eseguo il metodo incollato di seguito. Il metodo si blocca per un lungo periodo (600 secondi) prima che termini o si arresti. Se ho poche entità (500-1000) nel mio NStreeController ci vuole molto meno tempo rispetto a se ho un sacco di (200.000) entità per passare questo metodo, se non passa affatto. Quello che devo sapere è se c'è un modo migliore per cancellare/aggiornare/ripristinare il contenuto del mio NStreeController per cancellare il mio NSoutlineView prima di rieseguire il mio programma e riempire nuovamente il NStreeController. Nello specifico, vorrei che il mio NSOutlineView risponda rapidamente alle modifiche ai contenuti del mio NSTreeController, e ho bisogno del contenuto del mio core Data NSTreeController per poter essere resettato.Ripristina contenuto TreeController contenuto dati Core

-(void) cleanSDRDFileObjects 
{ 
    __weak __typeof__(self) weakSelf = self; 
    dispatch_async(dispatch_get_main_queue(), ^{  
     [weakSelf.outlineView collapseItem:nil collapseChildren:YES]; 
     [weakSelf.coreDataController._coreDataHelper.context performBlockAndWait:^{ 

      NSEntityDescription *entityDescription = [NSEntityDescription 
                entityForName:@"SDRDFileObject"          inManagedObjectContext:weakSelf.coreDataController._coreDataHelper.context]; 

      NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
      [request setEntity:entityDescription]; 

      NSArray * result = [weakSelf.coreDataController._coreDataHelper.context executeFetchRequest:request error:nil]; 
      for (id fileobject in result){ 
       [weakSelf.coreDataController._coreDataHelper.context deleteObject:fileobject]; 
      } 
      [weakSelf.coreDataController._coreDataHelper.context processPendingChanges]; 

      NSLog(@"Finished deleting all objects"); 
     }]; 
    }); 
} 

Il managedobjectcontext (context) viene eseguito come tipo NSMainQueueConcurrencyType e il metodo viene eseguito sul thread principale. Suggerimenti per miglioramenti, o esempi utili per la combinazione di reset/aggiornamento di NSOutlineView + Core Data sarebbero molto apprezzati. Grazie. Cheers, Trond

In risposta alla domanda @TomHarringtons ho scattato una foto del mio Time Profiler. Io davvero don t understand why it hangs on this method, however, after commenting this methods out (```processPendingChanges```), it still hangs and takes forever to finish (6 minutes). It seems the process gets stuck on the main thread and can t continuare.

enter image description here

Quando esegue nuovamente l'applicazione, con processPendingChanges commentato la sua ancora appeso.

enter image description here

Aggiornamento

credo ho risolto questo, ma io sono un po 'incerta sul motivo per cui questo ha funzionato. Sembra che il mio primo metodo sia entrato in un ciclo indefinito che non ha rilasciato i suoi oggetti. La seguente soluzione semplice lavorato:

 __weak __typeof__(self) weakSelf = self; 
    dispatch_sync(dispatch_get_main_queue(), ^{ 
     [weakSelf.coreDataController._coreDataHelper.context reset]; 
     }); 

ero certo che per svuotare correttamente un contesto oggetto gestito avrei dovuto eliminare ogni entità individuale. La funzione di reset sembra una forza bruta e in realtà pulisce la memoria e si assicura che tutto sia a posto? Se qualcuno vuole far luce su ciò che sarebbe apprezzato.

+0

will/doneChangeValueForKey viene generalmente chiamato dagli accessors dell'istanza 'self'. Perché li chiameresti con questo metodo? E NSTreeController non ha nemmeno un "figlio" keyPath. Ha un keyPath "childrenKeyPath". Indipendentemente da tutto ciò, stai cercando 'riorganizzaOggetti '?? – stevesliva

+0

['rearrangeObjects'] (http://stackoverflow.com/questions/23773827/how-can-i-determine-if-apple-methods-are-asynchronous/) a volte pianificherà l'aggiornamento della GUI nella coda principale dei thread, quindi potrebbe avere qualcosa a che fare con il tuo problema. Ciononostante, il tuo uso dei metodi KVC è spaventoso, e dovresti studiarlo prima di usare/didChangeValueForKey. Mi chiedo anche quando si spinge le modifiche dal contesto di sfondo al contesto mainThread/GUI. – stevesliva

+0

@stevesliva Grazie per i vostri commenti. Mi rendo conto di aver copiato e incollato il mio codice mentre stavo testando a caso KVO (Ill study). Ho usato KVO su arrangedObjects (senza successo). Ora vedo che il mio delegato outlineView si arresta in modo anomalo mentre sto eliminando le entità, soprattutto quando elimino un'entità prima di eliminare i suoi figli e la outlineview tenta di aggiornare un elemento deallocato. Se hai suggerimenti per la migliore pratica nel reimpostare una vista tabella o una vista panoramica guidata da Core Data sarebbe fantastico. Ho cercato su Google questo problema ma non riesco a trovare buoni esempi su come reimpostare una visualizzazione guidata dei dati principali. –

risposta

1

Guardando di nuovo, è stato recuperato tutti gli oggetti di un tipo in performBlockAndWait - questo blocca il thread principale perché si ha mainQueueConcurrency e si è utilizzata la versione andWait di performBlock.

Quindi si elimina ogni oggetto uno per uno. Questi oggetti si trovano in una struttura dati ad albero con una vista in serie allegata (vedere i messaggi KVO nella traccia dello stack). Questi oggetti hanno a-molte relazioni che devono essere mantenute dai dati principali, diavolo, potresti persino avere una regola di cancellazione a cascata. (vedi propagateDelete e maintainInverseRelationship nello stack trace) In ogni caso, inizi a richiedere che sia l'origine dati sia la vista inizino a fare molto lavoro, sul thread principale. Si potrebbe provare a utilizzare un MOC figlio con privateQueueConcurrency se si desidera iterare tutti gli oggetti sullo sfondo.

Ma, come i commenti indicati:

di NSManagedObjectContext reset sicuramente consente di liberare la memoria, ed è bene per quello che si vuole fare qui: soffiare via tutto.

Si pone quindi la domanda per quale motivo si carica il modello dallo store su disco in primo luogo.

Se si desidera che i dati del core, ma non la persistenza tra le volte che si esegue il programma, è possibile inizializzare il persistentStoreCoordinator con un archivio di NSInMemoryStoreType anziché puntarlo a un URL di file.

+0

Non conoscevo NSInMemoryStoreType e utilizzo solo i dati del core come "In memoria" (non la persistenza) quindi questo è un ottimo consiglio! Grazie! –

+0

L'ho sentito di recente suggerito a scopo di test ... è possibile scrivere test di unità che creano archivi in ​​memoria e li gettano via senza creare una posizione su disco per il proprio campo di prova. Ma in questo caso, si adatta anche alla fattura. – stevesliva