Domanda

Vorrei aggiungere il contenuto di un file sqlite (che è stato creato utilizzando Core Data con un modello A) a un altro archivio sqlite utilizzato dalla mia applicazione (che utilizza lo stesso modello A). L'idea è di importare rapidamente grandi quantità di dati.

Il problema che sto affrontando è che il codice seguente funziona solo una volta. Quando provo a eseguire lo stesso codice due volte, l'applicazione si bloccherà nella riga contrassegnata con il mio commento. Qualsiasi aiuto sarebbe molto apprezzato.

NSError **err;
NSURL *importURL = [NSURL fileURLWithPath:[[[NSBundle mainBundle] resourcePath]  stringByAppendingPathComponent: @"import.sqlite"]];
NSURL *storeURL = [NSURL fileURLWithPath:[[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"applicationdata.sqlite"]];
NSMigrationManager *migrator = [[NSMigrationManager alloc] initWithSourceModel:[self managedObjectModel] destinationModel:[self managedObjectModel]];
NSMappingModel *mappingModel = [NSMappingModel inferredMappingModelForSourceModel:[self managedObjectModel] destinationModel:[self managedObjectModel] error:err];
NSError **err2;

// the following line crashes when the whole block is ran twice
[migrator migrateStoreFromURL:importURL 
                         type:NSSQLiteStoreType 
                      options:nil 
             withMappingModel:mappingModel 
             toDestinationURL:storeURL 
              destinationType:NSSQLiteStoreType 
           destinationOptions:nil 
                        error:err2];

NSLog(@"import finished");
[migrator release];
È stato utile?

Soluzione

Vedo subito un errore in quel codice, che ha a che fare con l'argomento dell'errore di quella chiamata al metodo. NSError ** significa che si desidera dare al metodo l'indirizzo di un NSError * , che utilizzerà per scrivere un riferimento a un oggetto errore (se un errore si verifica). In questo momento stai solo passando un puntatore non inizializzato che potrebbe puntare a qualcosa di valido o potrebbe puntare alla spazzatura totale, a seconda di ciò che accade nello stack in quel momento. Il metodo del migratore scriverà a questo punto, a volte senza apparenti effetti negativi, ma a volte con conseguente arresto anomalo, come stai vedendo. Il codice per questo sarebbe simile a questo:

NSError *err2 = nil; //you want to initialize to nil, in case method doesn't modify your pointer at all (i.e. no error occurs)

//the method also returns a BOOL indicating success/failure
if (![migrator migrateStoreFromURL:importURL 
                     type:NSSQLiteStoreType 
                  options:nil 
         withMappingModel:mappingModel 
         toDestinationURL:storeURL 
          destinationType:NSSQLiteStoreType 
       destinationOptions:nil 
                    error:&err2])
{
    //handle the error
}

Altri suggerimenti

Grazie Brian per averlo segnalato.

Ho finito semplicemente aggiungendo il file sqlite aggiuntivo ai negozi persistenti dello stack, funziona molto bene e ci consente di limitare successivamente il fetchRequest ai singoli negozi:

NSError *error = nil;
NSURL *url = SOME_FILEPATH_URL;
NSPersistentStore *newStore = [persistentStoreCoordinator 
                                    addPersistentStoreWithType:NSSQLiteStoreType
                                                 configuration:nil
                                                           URL:url 
                                                       options:opt
                                                         error:&error];

E conserviamo un dizionario di tutti i persistentStores per riferimento futuro.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top