Dati fondamentali, in contesto best practice

Ho una grande attività di importazione di cui ho bisogno con i dati fondamentali.

Diciamo che il mio modello di dati di base simile a questa:

Car
----
identifier 
type

Recuperare un elenco di auto info JSON dal mio server e poi voglio sincronizzarlo con il mio core i dati Car oggetto, nel senso di:

Se la sua una nuova auto -> creare un nuovo Nucleo di Dati Car oggetto dal nuovo info.

Se l’auto che già esiste -> aggiorna i Dati principali Car oggetto.

Quindi voglio fare l’importazione in background, senza bloccare l’interfaccia utente e mentre l’uso di pergamene vetture in vista tabella presente che tutte le vetture.

Attualmente sto facendo qualcosa di simile a questo:

//create background context
NSManagedObjectContext *bgContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[bgContext setParentContext:self.mainContext];

[bgContext performBlock:^{
    NSArray *newCarsInfo = [self fetchNewCarInfoFromServer]; 

    //import the new data to Core Data...
    //I'm trying to do an efficient import here,
    //with few fetches as I can, and in batches
    for (... num of batches ...) {

        //do batch import...

        //save bg context in the end of each batch
        [bgContext save:&error];
    }

    //when all import batches are over I call save on the main context

    //save
    NSError *error = nil;
    [self.mainContext save:&error];
}];

Ma io non sono davvero sicuro che sto facendo la cosa giusta qui, per esempio:

È giusto che io uso setParentContext ?

Ho visto alcuni esempi che la utilizzano come questo, ma ho visto altri esempi che non chiamano setParentContext, invece che fare qualcosa di simile a questo:

NSManagedObjectContext *bgContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
bgContext.persistentStoreCoordinator = self.mainContext.persistentStoreCoordinator;  
bgContext.undoManager = nil;

Un’altra cosa che non so è quando si chiama salva il principale contesto, Nel mio esempio ho appena chiamata salvare alla fine dell’importazione, ma ho visto esempi che utilizza:

[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification object:nil queue:nil usingBlock:^(NSNotification* note) {
    NSManagedObjectContext *moc = self.managedObjectContext;
    if (note.object != moc) {
        [moc performBlock:^(){
            [moc mergeChangesFromContextDidSaveNotification:note];
        }];
    }
}];  

Come detto prima, voglio che l’utente sia in grado di interagire con i dati durante l’aggiornamento, così che cosa se l’utente modifica un tipo di auto, mentre l’importazione di modificare la stessa auto, è il modo in cui ho scritto sul sicuro?

AGGIORNAMENTO:

Grazie a @TheBasicMind grande spiegazione sto cercando di implementare Un opzione, quindi il mio codice simile a:

Questo è il Nucleo dei Dati di configurazione in AppDelegate:

AppDelegate.m  

#pragma mark - Core Data stack

- (void)saveContext {
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
            DDLogError(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }
}  

//main
- (NSManagedObjectContext *)managedObjectContext {
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    _managedObjectContext.parentContext = [self saveManagedObjectContext];

    return _managedObjectContext;
}

//save context, parent of main context
- (NSManagedObjectContext *)saveManagedObjectContext {
    if (_writerManagedObjectContext != nil) {
        return _writerManagedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _writerManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [_writerManagedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _writerManagedObjectContext;
}  

E questo è come il mio metodo di importazione sembra ora:

- (void)import {
    NSManagedObjectContext *saveObjectContext = [AppDelegate saveManagedObjectContext];

    //create background context
    NSManagedObjectContext *bgContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    bgContext.parentContext = saveObjectContext;

    [bgContext performBlock:^{
        NSArray *newCarsInfo = [self fetchNewCarInfoFromServer];

        //import the new data to Core Data...
        //I'm trying to do an efficient import here,
        //with few fetches as I can, and in batches
        for (... num of batches ...) {

            //do batch import...

            //save bg context in the end of each batch
            [bgContext save:&error];
        }

        //no call here for main save...
        //instead use NSManagedObjectContextDidSaveNotification to merge changes
    }];
}  

E anche io ho la seguente osservazione:

[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification object:nil queue:nil usingBlock:^(NSNotification* note) {

    NSManagedObjectContext *mainContext = self.managedObjectContext;
    NSManagedObjectContext *otherMoc = note.object;

    if (otherMoc.persistentStoreCoordinator == mainContext.persistentStoreCoordinator) {
        if (otherMoc != mainContext) {
            [mainContext performBlock:^(){
                [mainContext mergeChangesFromContextDidSaveNotification:note];
            }];
        }
    }
}];
  • Se si utilizza il genitore-bambino modello per salvare il bambino e il genitore per ottenere il database per aggiornare correttamente.
  • questa è parte della mia domanda, devo utilizzare un genitore-bambino modello per questo tipo di attività? e qual è il mio altre opzioni?
  • vi consigliamo di visitare questo post vi possa essere d’aiuto raywenderlich.com/15916/…
  • perché? Da Dati di base Manuale di Programmazione: la Concorrenza: Once all of the data has been consumed and turned into NSManagedObject instances, you call save on the private context, which moves all of the changes into the main queue context without blocking the main queue. developer.apple.com/library/ios/documentation/Cocoa/Conceptual/…
  • cercando di fare un efficiente importa qui” Cosa significa?
  • Ciao @Eyal, non è in grado di risolvere il tuo problema, in caso affermativo, si prega di condividere la risposta, perché ho lo stesso problema.

InformationsquelleAutor Eyal | 2014-07-09



3 Replies
  1. 170

    Questo è un estremamente confusa argomento per le persone che si avvicinano di Dati di base per la prima volta. Non dico questo con leggerezza, ma con l’esperienza, sono fiducioso dicendo la documentazione di Apple è un po ‘ fuorviante in materia (è, infatti, coerente se hai letto molto attentamente, ma non adeguatamente illustrati i motivi per cui l’unione dei dati rimane in molti casi una soluzione migliore che affidarsi a padre/figlio contesti e semplicemente il salvataggio di un bambino per il genitore).

    La documentazione dà l’impressione di un genitore/bambino contesti sono il nuovo modo preferito per fare l’elaborazione in background. Tuttavia Apple trascurare di evidenziare alcuni caveat. In primo luogo, essere consapevoli del fatto che tutto ciò che si recupera in tuo bambino il contesto è tirato attraverso il suo genitore. Quindi è meglio limitare qualsiasi bambino del contesto in esecuzione sul thread principale per l’elaborazione (modifica) dei dati che è già stato presentato nell’interfaccia utente sul thread principale. Se si utilizza generali per le operazioni di sincronizzazione è probabile che vi verrà voglia di dati di processo che si estende ben oltre i confini di ciò che si sta attualmente visualizzato nell’interfaccia utente. Anche se si utilizza NSPrivateQueueConcurrencyType, per il bambino modifica il contesto, si sarà potenzialmente trascinando una grande quantità di dati attraverso il contesto e che può portare a cattive prestazioni e il blocco. Ora è meglio non fare il contesto di un bambino di contesto si utilizza per la sincronizzazione, perché non sarebbe una notifica di sincronizzazione aggiornamenti a meno che non avete intenzione di farlo manualmente, più si sarà in esecuzione potenzialmente a lungo l’esecuzione di compiti in un contesto potrebbe essere necessario per rispondere a risparmiare iniziato come una cascata dalla modifica contesto che è un figlio di tuo contesto, attraverso il contatto principale e giù per l’archivio dati. Sarà necessario unire manualmente i dati e anche, eventualmente, tenere traccia di ciò che ha bisogno di essere invalidata nel contesto e re-sync. Non il più semplice modello.

    Che la documentazione di Apple non mettere in chiaro è che è più probabile che sia necessario un ibrido delle tecniche descritte nelle pagine che descrivono il “vecchio” thread confinamento modo di fare le cose, e il nuovo Padre-Figlio contesti modo di fare le cose.

    La vostra scommessa migliore è probabilmente (e mi sto dando una soluzione generica qui, la soluzione migliore potrebbe dipendere la mappa requisiti), per un NSPrivateQueueConcurrencyType salvare contesto come la prima genitore, che salva direttamente all’archivio dati. [Edit: non è molto direttamente in questo contesto], quindi dare che salva contesto almeno due bambini. Una vostra NSMainQueueConcurrencyType contesto di utilizzare per l’UTENTE [Edit: è meglio essere disciplinato e di evitare di fare qualsiasi modifica dei dati in questo contesto], l’altro è un NSPrivateQueueConcurrencyType, si usa fare l’utente modifica dei dati (in opzione A, l’allegato schema) il tuo le operazioni di sincronizzazione.

    Poi si crea il contesto di destinazione del NSManagedObjectContextDidSave notifica generato dalla sincronizzazione contesto, e inviare le notifiche .userInfo dizionario principale del contesto mergeChangesFromContextDidSaveNotification:.

    La prossima questione da considerare è dove si mette all’utente di modificare il contesto (il contesto in cui le modifiche apportate dall’utente, si riflettono nell’interfaccia). Se le azioni dell’utente sono sempre solo modifiche di piccole quantità di dati presentati, quindi, rendendo questo un bambino di il contesto di nuovo utilizzando il NSPrivateQueueConcurrencyType è la vostra scommessa migliore e più semplice da gestire (salva salva le modifiche direttamente nel contesto e se si dispone di un NSFetchedResultsController, l’appropriato metodo di delegato, sarà chiamato automaticamente in modo che l’interfaccia utente in grado di elaborare gli aggiornamenti controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:) (anche questo è Un opzione).

    Se, invece, le azioni dell’utente potrebbe portare a grandi quantità di dati in fase di elaborazione, si potrebbe desiderare di prendere in considerazione di fare un altro peer del contesto e la sincronizzazione di contesto, in modo tale che salva il contesto di tre figli diretti. principale, sync (privato tipo di coda) e modifica (privato tipo di coda). Ho mostrato questo accordo come opzione B nel diagramma.

    Allo stesso modo per la sincronizzazione contesto sarà necessario [Edit: configurare il principale contesto di ricevere le notifiche] quando i dati vengono salvati (o se avete bisogno di un maggiore livello di granularità, quando i dati sono aggiornati) e prendere un’azione per unire i dati (in genere utilizzando mergeChangesFromContextDidSaveNotification:). Si noti che con questa disposizione, non vi è alcuna necessità per il contesto di chiamare il salvataggio: il metodo.
    Dati fondamentali, in contesto best practice

    Per capire le relazioni padre/figlio, prendere l’Opzione A: padre-figlio approccio semplicemente significa che se la modifica contesto recupera NSManagedObjects, saranno “copiato in” (registrato) prima salva contesto, poi il contesto, poi, infine, modificare il contesto. Si sarà in grado di apportare delle modifiche, quindi quando si chiama salva: la modifica del contesto, le modifiche verranno salvate solo per il contesto di. Si dovrebbe chiamare salvare: il contesto e quindi chiamare salva: salva il contesto prima di essere scritti su disco.

    Quando si salva da un bambino, fino a un genitore, i vari NSManagedObject di modificare e salvare le notifiche sono licenziato. Così, per esempio, se si utilizza una fetch risultati controller per gestire i tuoi dati per l’interfaccia utente, è delegato metodi vengono chiamati in modo da poter aggiornare l’interfaccia utente, come appropriato.

    Alcune conseguenze: Se si recupera l’oggetto e NSManagedObject Una modifica del contesto, quindi modificare, e salvare, in modo che le modifiche vengono restituiti al contesto. Ora hai modificato l’oggetto ha registrato contro sia la principale e la modifica del contesto. Sarebbe un cattivo stile di farlo, ma ora è possibile modificare l’oggetto di nuovo sul contesto e non sarà diverso dall’oggetto, come è archiviato nella modifica del contesto. Se si tenta di apportare ulteriori modifiche all’oggetto memorizzato nella modifica contesto, le modifiche verranno sincronizzate con l’oggetto principale di contesto, e qualsiasi tentativo di salvare la modifica contesto genererà un errore.

    Per questo motivo, con un arrangiamento come opzione, è un buon motivo per provare a recuperare gli oggetti, modificare, salvare e ripristinare la modifica del contesto (ad esempio, [editContext reset] con ogni singola iterazione del loop (o all’interno di ogni blocco passato al [editContext performBlock:]). E ‘ anche meglio di disciplina, di evitare di fare sempre qualsiasi di modifiche sul contesto.
    Inoltre, per ripetere, in quanto tutte le operazioni di elaborazione principale è il thread principale, se si scarica un sacco di oggetti per la modifica quadro, il contesto fa la elaborazione di recupero sul thread principale come gli oggetti vengono copiati in giù, in modo iterativo, da genitore a figlio contesti. Se c’è un sacco di dati oggetto di trattamento, questo può causare il blocco dell’interfaccia utente. Così se, per esempio, si dispone di un grande negozio di oggetti gestiti, e si dispone di un interfaccia utente opzione che sarebbe risultato in fase di modifica. Non sarebbe una cattiva idea, in questo caso, configurare l’App come opzione A. In tal caso l’opzione B è una scommessa migliore.

    Se non con l’elaborazione di migliaia di oggetti, quindi l’opzione A, può essere del tutto sufficiente.

    BTW non preoccupatevi troppo su quale opzione scegliere. Potrebbe essere una buona idea per iniziare con Una e se è necessario modificare per B. e ‘ più facile di quanto si potrebbe pensare di fare un tale cambiamento e di solito ha meno conseguenze di quanto si potrebbe aspettare.

    • grazie (e +1) per la risposta dettagliata, a questo punto del mio sviluppo sarà un grande cambiamento è l’aggiunta di questi contesti. Ho davvero solo si desidera utilizzare un extra di contesto per fare questa attività in background e tenerlo il più semplice possibile. Io ancora non capisco la differenza tra padre-figlio approccio e le altre alternative. Apprezzo se si può prendere il mio codice di esempio e correggere eventuali errori di passaggi che ho fatto lì, in modo che sarà più facile per me capire e da fare.
    • Prendere l’Opzione A. padre-figlio approccio semplicemente significa che se la modifica contesto recupera NSManagedObjects, saranno “copiato in” (registrato) prima salva contesto, poi il contesto, poi, infine, modificare il contesto. Si sarà in grado di apportare delle modifiche, quindi quando si chiama salva: la modifica del contesto, le modifiche verranno salvate solo per il contesto. Si dovrebbe chiamare salvare: il contesto e quindi chiamare salva: salva prima che vengano scritti su disco. Potrai modificare la mia risposta.
    • Sono così contento che hai deciso di rispondere qui, la tua info è impagabile. Credo di avere più fiducia ora di provare questo fuori, ho solo bisogno di fare un po ‘ di ordine a tutte queste info nella mia testa. La modifica contesto mi confonde un po’, che cosa è la diff tra questo e qualsiasi altro contesto? perché lui è un bambino e la sincronizzazione contesto non lo è? Comunque per ora penso che io non uso un contesto separato per fare le modifiche effettuate dall’utente, poiché l’utente può eliminare solo un elemento di(Auto) in un momento o modificare una proprietà, uno alla volta, in modo da fare ogni modifica con il contesto e chiamare direttamente salvare: su di esso.
    • Ho anche aggiornato la mia domanda con il nuovo codice che ho scritto cercando di implementare l’opzione A (meno la Modifica del contesto di bambino). può u si prega di controllare se il suo fine, non sono sicuro, devo chiamare salva: Salva contesto ovunque? o basta unire le modifiche nella notifica?
    • Grande risposta dettagliata. Il mio vota !!!
    • quando è il momento di salvare il “salvare” il contesto? Fate questo indipendente dall’interazione dell’utente?
    • Padre/Figlio contesto non sono per l’elaborazione in background. Sono per atomic aggiornamenti di dati correlati che potrebbero essere creati in più view controller. Quindi, se l’ultimo controller di visualizzazione viene annullata, il bambino di contesto può essere gettato via senza effetti negativi sul bilancio.
    • wow l’uomo, l’inferno di una buona spiegazione, grazie mille!
    • In opzione, la Modifica Contesto potrebbe essere creato con ‘NSConfinementConcurrencyType’, non c’è bisogno di una coda privata. Probabilmente modificare in un sub ViewController che è sul thread principale comunque. Vedere la nota in conclusione: cocoanetics.com/2012/07/multi-context-coredata
    • Per tutti coloro che amano questa domanda, mi può anche raccomandare a guardare WWDC 2012 – Sessione 214 – Dati di base Best Practice.
    • Può darci un esempio di struttura di coredata con la concorrenza che si parla di pattern, github link kinder. può essere che di aiuto a tutti noi. Ehi @TheBasicMind ho un problema quando cerco di creare mainManagedObjectContext(oggetto lazy) in più thread stesso tempo, per la prima volta la mia app get crash. se si tenta di creare in mainthread funziona benissimo.(causa perché in parallelo thread per creare mainManagedObjectContext) qual è il modo migliore per farlo?
    • È tutto da questa risposta si validi / necessari, con iOS 10? Visualizzare altre risposte di parte che inizia con “In iOS 10 Apple spostato la sincronizzazione da sqlite a livello di file fino alla persistente coordinatore…”
    • c’è qualche riferimento su Firstly, be aware that everything you fetch into your child context is first pulled through it's parent
    • Ciao per favore mi potete aiutare con questo stackoverflow.com/questions/50055953/…

  2. 13

    In primo luogo, padre/figlio contesto non sono per l’elaborazione in background. Sono per atomic aggiornamenti di dati correlati che potrebbero essere creati in più view controller. Quindi, se l’ultimo controller di visualizzazione viene annullata, il bambino di contesto può essere gettato via senza effetti negativi sul bilancio. Questo è spiegato da Apple in fondo a questa risposta a [^1]. Ora che è fuori strada e non è caduto per un errore comune, è possibile concentrarsi su come far bene il background di Dati di base.

    Creare un nuovo archivio permanente coordinatore (non è più necessario su iOS 10 vedere aggiornamento di seguito) e una coda privata contesto. Ascoltare per la notifica di salvataggio e di unire le modifiche nel contesto (su iOS 10 il contesto ha una struttura per fare questo automaticamente)

    Per un campione da Apple, vedere “Terremoti: la Compilazione di un Core Archivio di Dati Utilizzando uno Sfondo di Coda”
    https://developer.apple.com/library/mac/samplecode/Earthquakes/Introduction/Intro.html
    Come si può vedere dalla cronologia di revisione sul 2014-08-19 hanno aggiunto
    “Il nuovo codice di esempio che mostra come utilizzare un secondo Nucleo di Dati stack per il recupero dei dati su uno sfondo di coda.”

    Qui è che il bit da AAPLCoreDataStackManager.m:

    //Creates a new Core Data stack and returns a managed object context associated with a private queue.
    - (NSManagedObjectContext *)createPrivateQueueContext:(NSError * __autoreleasing *)error {
    
        //It uses the same store and model, but a new persistent store coordinator and context.
        NSPersistentStoreCoordinator *localCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[AAPLCoreDataStackManager sharedManager].managedObjectModel];
    
        if (![localCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil
                                                      URL:[AAPLCoreDataStackManager sharedManager].storeURL
                                                  options:nil
                                                    error:error]) {
            return nil;
        }
    
        NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [context performBlockAndWait:^{
            [context setPersistentStoreCoordinator:localCoordinator];
    
            //Avoid using default merge policy in multi-threading environment:
            //when we delete (and save) a record in one context,
            //and try to save edits on the same record in the other context before merging the changes,
            //an exception will be thrown because Core Data by default uses NSErrorMergePolicy.
            //Setting a reasonable mergePolicy is a good practice to avoid that kind of exception.
            context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
    
            //In OS X, a context provides an undo manager by default
            //Disable it for performance benefit
            context.undoManager = nil;
        }];
        return context;
    }

    E in AAPLQuakesViewController.m

    - (void)contextDidSaveNotificationHandler:(NSNotification *)notification {
    
        if (notification.object != self.managedObjectContext) {
    
            [self.managedObjectContext performBlock:^{
                [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
            }];
        }
    }

    Ecco la descrizione completa di come il campione è stato progettato:

    Terremoti: l’Utilizzo di un “privato” archivio permanente di coordinatore per recuperare i dati in background

    La maggior parte delle applicazioni che utilizzano i Dati principali di utilizzare un unico archivio permanente di coordinatore per mediare l’accesso ad un archivio permanente. Terremoti mostra come utilizzare un ulteriore “privato” archivio permanente coordinatore durante la creazione di oggetti gestiti utilizzando i dati recuperati da un server remoto.

    Architettura Dell’Applicazione

    L’applicazione utilizza due Dati fondamentali, in “pile” (come definito dall’esistenza di un archivio permanente di coordinatore). Il primo è il tipico “general purpose” stack; il secondo è creata da un view controller appositamente per recuperare i dati da un server remoto (Come di iOS 10 a seconda del coordinatore non è più necessario, vedere aggiornamento in fondo alla risposta).

    Il principale archivio permanente coordinatore è a pagamento da un singleton “stack controller” oggetto (istanza di CoreDataStackManager). È responsabilità dei propri clienti, per creare un oggetto gestito in un contesto di lavoro con il coordinatore[^1]. Lo stack controller, inoltre, della vendita delle proprietà per l’oggetto gestito modello utilizzato dall’applicazione, e la posizione di un archivio permanente. I clienti possono usufruire di queste ultime proprietà per impostare ulteriori archivio permanente dei coordinatori di lavorare in parallelo con il coordinatore principale.

    Principale view controller, un’istanza di QuakesViewController, usa la pila del controller archivio permanente di coordinatore per recuperare tremiti dall’archivio permanente per visualizzare in una tabella. Il recupero dei dati dal server può essere un’operazione di lunga durata che richiede una significativa interazione con l’archivio permanente per determinare se i record recuperati dal server sono nuovo tremiti o eventuali aggiornamenti esistenti tremiti. Per garantire che l’applicazione può rimanere attivo durante questa operazione, il view controller utilizza una seconda coordinatore per gestire l’interazione con l’archivio permanente. Configura il coordinatore di utilizzare lo stesso modello di oggetto gestito e persistente store come il principale coordinatore del pagamento da stack controller. Crea un oggetto gestito contesto legato a una coda privata per il recupero dei dati da memorizzare ed eseguire il commit delle modifiche all’archivio.

    [^1]: Questo sostiene il “passare il testimone” approccio in base al quale—in particolare in applicazioni iOS—un contesto che è passato da un controller di visualizzazione all’altra. Il root view controller è responsabile per la creazione di contesto iniziale, e passando per bambino view controller come/quando necessario.

    Il motivo per cui questo modello è quello di garantire che le modifiche apportate all’oggetto gestito grafico sono opportunamente vincolata. Dati di base supporta “nested” oggetto gestito contesti che permettono un’architettura flessibile che lo rendono facile per il supporto indipendente, annullabile, set di modifica. Con un bambino di contesto, è possibile consentire all’utente di effettuare una serie di modifiche di oggetti gestiti che può essere commesso all’ingrosso per il genitore (e, in definitiva, salvato al negozio) come una singola transazione o scartato. Se tutte le parti dell’applicazione semplicemente recuperare lo stesso contesto, per esempio, un’applicazione delegato, rende questo comportamento difficile o impossibile per il supporto.

    Aggiornamento: In iOS 10 Apple spostato la sincronizzazione da sqlite a livello di file fino alla persistente coordinatore. Questo significa che è ora possibile creare una coda di contesto e il riuso dell’esistente coordinatore utilizzato dal contesto, senza gli stessi problemi di prestazioni che si sarebbe dovuto fare prima, cool!

  3. 4

    Dal modo in cui questa documento di Apple è spiegare questo problema in modo molto chiaro. Swift versione di cui sopra per chiunque sia interessato

    let jsonArray =  //JSON data to be imported into Core Data
    let moc =  //Our primary context on the main queue
    
    let privateMOC = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
    privateMOC.parentContext = moc
    
    privateMOC.performBlock {
        for jsonObject in jsonArray {
            let mo =  //Managed object that matches the incoming JSON structure
            //update MO with data from the dictionary
        }
        do {
            try privateMOC.save()
            moc.performBlockAndWait {
                do {
                    try moc.save()
                } catch {
                    fatalError("Failure to save context: \(error)")
                }
            }
        } catch {
            fatalError("Failure to save context: \(error)")
        }
    }

    E ancora più semplice se si utilizza NSPersistentContainer per iOS 10 e sopra

    let jsonArray = 
    let container = self.persistentContainer
    container.performBackgroundTask() { (context) in
        for jsonObject in jsonArray {
            let mo = CarMO(context: context)
            mo.populateFromJSON(jsonObject)
        }
        do {
            try context.save()
        } catch {
            fatalError("Failure to save context: \(error)")
        }
    }
    • come recuperare dati potete per favore dare l’esempio perché ho si blocca in modo casuale durante il recupero e, a volte, funziona correttamente. @hariszaman
    • Potrebbe essere che si sta tentando di modificare e salvare il contesto allo stesso tempo

Lascia un commento