2012-08-22 14 views
16

Ho seguito le istruzioni these per aiutare ad integrare il supporto iCloud con CoreData e sto ricevendo alcuni errori.CoreData 'Questo NSPersistentStoreCoordinator non ha archivi persistenti. Non può eseguire un'operazione di salvataggio. '

ho questo nel mio AppDelegate:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 

    if (persistentStoreCoordinator != nil) { 
     return persistentStoreCoordinator; 
    } 

    //NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Little_Wedding_Book_Universal.sqlite"]; 
    NSString *storePath = [[NSString stringWithFormat:@"%@", [self applicationDocumentsDirectory]] stringByAppendingPathComponent:@"appname.sqlite"]; 
    NSURL *storeURL = [NSURL fileURLWithPath:storePath]; 

    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 

    NSPersistentStoreCoordinator* psc = persistentStoreCoordinator; 

    if (IOS_VERSION_GREATER_THAN_OR_EQUAL_TO(@"5.0")) 
    { 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
      NSFileManager *fileManager = [NSFileManager defaultManager]; 

      // Migrate datamodel 
      NSDictionary *options = nil; 

      // this needs to match the entitlements and provisioning profile 
      NSURL *cloudURL = [fileManager URLForUbiquityContainerIdentifier:@"J9VXW4WCE8.com.company.appname"]; 
      NSString* coreDataCloudContent = [[cloudURL path] stringByAppendingPathComponent:@"data"]; 
      if ([coreDataCloudContent length] != 0) { 
       // iCloud is available 
       cloudURL = [NSURL fileURLWithPath:coreDataCloudContent]; 

       options = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
          [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, 
          @"appname.store", NSPersistentStoreUbiquitousContentNameKey, 
          cloudURL, NSPersistentStoreUbiquitousContentURLKey, 
          nil]; 
      } 
      else 
      { 
       // iCloud is not available 
       options = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
          [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, 
          nil]; 
      } 

      NSError *error = nil; 
      [psc lock]; 
      if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) 
      { 
       NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
       abort(); 
      } 
      [psc unlock]; 

      dispatch_async(dispatch_get_main_queue(), ^{ 
       NSLog(@"asynchronously added persistent store!"); 
       [[NSNotificationCenter defaultCenter] postNotificationName:@"RefetchAllDatabaseData" object:self userInfo:nil]; 
      }); 

     }); 

    } 
    else 
    { 
     NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
           [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
           [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, 
           nil]; 

     NSError *error = nil; 
     if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) 
     { 
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
      abort(); 
     } 
    } 

    return persistentStoreCoordinator; 
} 

In un altro controller di vista che crea un'istanza della mia AppDelegate, creare un oggetto e chiamare [appDelegate saveContext]; Questo è dove l'applicazione si blocca. Questo ha sempre funzionato perfettamente (fino ad ora, aggiungendo il supporto iCloud).

-(void)saveContext 
{ 
    NSError *error; 
    if (managedObjectContext != nil) { 
     if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { 
      // Update to handle the error appropriately. 
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
      exit(-1); // Fail 
     } 
    } 
} 

Così si blocca a questo metodo, e la console mi dà questo messaggio:

'NSInternalInconsistencyException', reason: 'This NSPersistentStoreCoordinator has no persistent stores. It cannot perform a save operation.' 

Non so cosa fare, aiuto!

EDIT: log della console di seguito:

Su lanciare l'applicazione, ottengo:

2012-08-22 17:39:47.906 appname[24351:707] asynchronously added persistent store! 
2012-08-22 17:39:47.955 appname[24351:707] asynchronously added persistent store! 

Seguito quando l'applicazione si blocca con:

2012-08-22 17:41:31.657 appname[24351:707] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'This NSPersistentStoreCoordinator has no persistent stores. It cannot perform a save operation.' 
*** First throw call stack: 
(0x3749d88f 0x351a2259 0x36bf0fe7 0x36c59287 0xd648b 0x149e0b 0x373f73fd 0x3118ce07 0x3118cdc3 0x3118cda1 0x3118cb11 0x3118d449 0x3118b92b 0x3118b319 0x31171695 0x31170f3b 0x33bb322b 0x37471523 0x374714c5 0x37470313 0x373f34a5 0x373f336d 0x33bb2439 0x3119fcd5 0xd53dd 0xd5378) 
terminate called throwing an exception(lldb) 
+0

Il thread in background (che ottiene l'archivio persistente di iCloud) è già terminato prima di salvare il contesto? –

+0

Qual è il modo migliore per verificarlo? –

+0

Il tuo codice fa un 'NSLog (@" asincrono aggiunto archivio permanente! ");' Quando il thread in background ha finito, quindi dovresti vederlo. –

risposta

22

Probabilmente si sta chiamando persistentStoreCoordinator metodo da due (o più) thread differenti. O direttamente o indirettamente.

Come scritto questo metodo non è thread-safe.

Potrebbe essere che tu abbia altri metodi con lo stesso problema. Tipicamente managedObjectContext esiste ed è scritto in modo simile.

Ci sono due modi per risolvere questo problema:

  • uso @synchronize rendere tali metodi thread-safe
  • spostare il codice di inizializzazione di loro e in un metodo init e modificarli per affermare/tranne se l'Ivar è nil

la seconda cosa che si può anche fare male è quello di modificare il contesto (ad esempio l'aggiunta di nuovi oggetti gestiti ad esso) e poi cercando di salvarlo, prima che il negozio è stato initiali Zed.

per risolvere questo assicurarsi che fare sia una delle seguenti:

  • non aggiungi qualsiasi oggetto gestito al contesto se non si sa c'è già almeno un oggetto gestito in esso (che implica il negozio è caricato)
  • se è necessario aggiungere un oggetto gestito al contesto senza verificare che ce ne sia già uno (ad esempio dopo aver inizialmente creato il negozio vuoto), assicurarsi che il negozio sia già stato inizializzato (ad esempio, farlo quando si ottenere la notifica RefetchAllDatabaseData e si nota che il database è vuoto).
+0

Sto affrontando lo stesso problema come Josh Kahane ma per favore dimmi come posso usare "synchronize" in persistentStoreCoordinator? Per favore, rispondimi –

40

Ho avuto lo stesso problema e la mia soluzione era eliminare l'applicazione e installarla di nuovo a causa di modifiche nel database.

+0

Penseresti che ora mi piacerebbe ricordare questo.Grazie per avermelo ricordato velocemente! –

+0

ha funzionato per me .. grazie – Saranjith

+1

Questo funziona solo se non hai pranzato la tua app nell'app store. Altrimenti si risolverà in un'app che si blocca per tutti gli utenti che hanno scaricato la versione precedente e l'hanno aggiornata con la tua nuova versione. –

0

Aggiornamento rif. XCODE 4.6.3 e MacOSX 10.9.5:

Per risolvere il problema ho rimosso la directory di applicazione relative al prodotto in Xcode derivato dati di posizione:

rm -rd/Users // Library/Developer/Xcode/DerivedData /. Apparentemente i dati vengono incasinati dopo aver giocato con il modello a oggetti.

1

risolto spostando il moc let = DataController() managedObjectContext. All'inizio della classe anziché lasciare all'interno della seedPerson func()

2

ho risolto rimuovendo l'applicazione da simulatore ed eseguirlo nuovamente. Immagino che accada perché la versione precedente dell'app non contiene dati di base.

0

Ho visto questo errore durante il test quando ho eseguito il routing di alcuni valori temporanei NSManagedObjectContext s senza aggrapparli a nessuno, il contesto veniva rilasciato a caso da ARC.

Ciò che ha funzionato è stato mantenere un riferimento al MOC sui test e reimpostarlo per ciascun test.

Non so quanto sia rilevante per le circostanze non di test, ma in particolare se si utilizzano contesti figlio/fratello, vale la pena assicurarsi che siano ancora lì. : P

0

Ho anche bloccato questo problema. Per questo motivo devo prima controllare il codice di migrazione dei dati di base Poiché il codice era corretto nel mio caso, ho cancellato la mia app dal dispositivo e reinstallata. E funziona.

0

Ho avuto lo stesso problema. Il motivo per cui l'errore era dovuto al fatto che avevo apportato alcune modifiche minori a nello schema di Entità CoreData (in pratica ho aggiunto 2-3 nuovi attributi). E me ne sono dimenticato perché non dà errori finché non lo eseguiamo. Quindi, ciò che accade è che l'app che era in esecuzione in precedenza aveva già lo store persistente con lo schema precedente. Quindi il nuovo schema punta allo stesso negozio. Questo è il motivo per cui rileviamo l'errore quando lo eseguiamo mentre proviamo ad accedere ai nuovi attributi.

Soluzione: Eliminare l'app dal dispositivo/simulatore. E reinstallarlo. (La nuova build avrà il nuovo schema e quindi non si arresta.)

Problemi correlati