2016-08-25 2 views
1

Einige Hintergrundinformationen für dieses Problem, ich versuche, was ich denke, relevant zu sein, um den Kontext zu verstehen.iOS-Core-Daten saveContext-Methode ist aufgrund NSSQLiteErrorDomain = 1032 fehlgeschlagen

Ich bin gerade dabei, eine verknüpfte Bibliothek hinzuzufügen, die Core-Daten verwendet, um einige Benutzerinformationen zu speichern, und eine Funktion, die eine Entität zu dem bereits vorhandenen Core Data-Modell in der App hinzufügt. Jeder managedObjectContext hat eine eigene Instanz, wenn er erstellt (verifiziert) wird, sowie seine eigene PSC und MOM und beide interagieren nicht mit den Entitäten des anderen (sie scheinen also unabhängig zu sein).

Der gesamte folgende Code, Fehler und (glaube ich, Problem) ist im Hauptziel der App. (Hoffentlich) nicht die neu hinzugefügte verknüpfte Bibliothek.

Die saveContext Methode ist:

- (void)saveContext { 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     NSError *error = nil; 
     // Register 
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myManagedObjectContextDidSaveNotificationHandler:) name:NSManagedObjectContextDidSaveNotification object:self.managedObjectContext]; 

     if (self.managedObjectContext != nil) { 
      if ([self.managedObjectContext hasChanges]) { 
       BOOL success = [self.managedObjectContext save:&error]; 
       if (!success) { 
        [Error showErrorByAppendingString:NSLocalizedString(@"UnableToSaveChanges", nil) withError:error]; 
       } else { 
        // 
       } 
      } 
     } 
     // Unregister 
     [[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:self.managedObjectContext]; 
    }); 
} 

Wenn sie aufgerufen wird, Fehler = nil, Erfolg = NO und durch den Compiler Vergangenheit Ausnahme zwingt erhalte ich folgendes:

CoreData: error: exception during obtainPermenantIDsForObjects: Updating max pk failed: attempt to write a readonly database with userInfo of { NSSQLiteErrorDomain = 1032; }

Ich habe gegoogelt , "NSSQLiteErrorDomain = 1032", "requirePermenantIDsForObjects" und "CoreData reeonly-Datenbank". Es scheint, dass der Schlüssel Primärschlüssel für jedes Objekt gleich ist, aber ich setze diesen Wert, ich glaube sqlite ist. Ich habe keine Lösungen gefunden, um damit zu helfen. Ich habe das Argument beim Start übergeben, "Concurrency Debug 1" auf aktiviert.

Ich habe nicht implementiert erhaltenPermenantIDsForObjects und ich habe das gesamte Projekt durchsucht und kann seine Implementierung nicht finden, so denke ich, dass CoreData dies verwendet.

Die saveContext-Methode wird in der Hauptwarteschlange aufgerufen, weil meine Vorgänger den Code ausgerollt haben und ich momentan keine Zeit habe, damit umzugehen.

Der Aufruf der Methode saveContext (von einem Hintergrund-Thread):

- (NSMutableArray *)convertRawStepDataTo:(NSMutableArray*)steps 
          withDates:(NSMutableArray*)dates 
       inManagedObjectContext:(NSManagedObjectContext*)theMOC { 

    NSMutableArray *theStepsArray = [[NSMutableArray alloc] init]; 

    // prepare values for chart 
    AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate; 
    StepSelector *theSelector = [[StepSelector alloc] init]; 
    NSString* apiSelectionForStep = [theSelector getCurrentSelectionString]; 

    for (int iter = 0; iter < steps.count; iter++) { 
     NSNumber *currStepValue = [steps objectAtIndex:iter]; 
     // NSNumber *stepCountforIter = [NSNumber numberWithLong:[[steps objectAtIndex:iter] longValue]]; 

     NSNumber* dateForIter = [NSNumber numberWithLong:[[dates objectAtIndex:iter] longLongValue]]; 
     Step *step = [delegate addStepObjectToPersistentStorewithAPI:apiSelectionForStep 
                 andStep:stepCountforIter 
                 andDate:dateForIter 
                  forMOC:theMOC]; 

     [theStepsArray addObject:step]; 

     if (VERBOSE) { 
      NSLog(@"This is step number %d, with object ID: %@", count, [theMOC objectWithID:step.objectID]); 
      count++; 
     } 
    } 
    [delegate saveContext]; 
    return theStepsArray; 
} 

Das ist alles, was ich denken kann, das könnte helfen. Die Quelle für den MOC im Hauptziel ist das appDelegate, in dem der gesamte Kerndatencode ursprünglich geschrieben wurde.

BEARBEITEN Hier ist der angeforderte PSC-Code. Das Geschäft befindet sich im Dokumentenverzeichnis. Ich habe festgestellt, dass diese Objekte im permanenten Speicher gespeichert werden. Der Fehler tritt jedoch immer noch auf. Se unten für PSC-Code:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 
    if (persistentStoreCoordinator != nil) { 
     return persistentStoreCoordinator; 
    } 

    NSURL *storeUrl = [self getStoreURL]; 

    // Rollback journalling mode... 
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
          [NSNumber numberWithBool:YES],NSInferMappingModelAutomaticallyOption, 
          NSFileProtectionComplete, NSFileProtectionKey, 
          @{@"journal_mode": @"TRUNCATE"}, NSSQLitePragmasOption, nil]; 

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

    NSError *error = nil; 
    self.persistentStore = [persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]; 
    if (!self.persistentStore) { 
     NSLog(@"Error: %@",error); 
     [Error showErrorByAppendingString:NSLocalizedString(@"UnableToFindDatabaseFile", nil) withError:error]; 
    } 

    return persistentStoreCoordinator; 
} 

-(NSURL *)getStoreURL { 
    NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: kSQLFILENAME]; 
    /* 
    Set up the store. 
    For the sake of illustration, provide a pre-populated default store. 
    */ 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    // If the expected store doesn't exist, copy the default store. 
    if (![fileManager fileExistsAtPath:storePath]) { 
     NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:SQLFILEPATHRESOURCE ofType:@"sqlite"]; 
     if (defaultStorePath) { 
      [fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL]; 
     } 
    } 

    NSURL *storeUrl = [NSURL fileURLWithPath:storePath]; 

    return storeUrl; 
} 
+0

Wie erstellen Sie den persistenten Speicher und wo befindet sich die SQLite-Datei? – Wain

+1

@Wain Aktualisierte Frage mit Antworten auf Ihre Frage. Hoffnung, die es klarer macht. – Randoramma

Antwort

1

Die NSSQLiteErrorDomain Schlüssel bedeutet, dass dieser Fehler von SQLite kam, und dass Core Data vergeht es an Sie zurück. SQLite defines error 1032 as follows:

The SQLITE_READONLY_DBMOVED error code is an extended error code for SQLITE_READONLY. The SQLITE_READONLY_DBMOVED error code indicates that a database cannot be modified because the database file has been moved since it was opened, and so any attempt to modify the database might result in database corruption if the processes crashes because the rollback journal would not be correctly named.

... die, dass SQLite zu bedeuten scheint, ist die persistenten Speicher Datei nur lesen machen, weil etwas, um es passiert ist, seit es eröffnet wurde, und SQLite versucht, Daten Korruption zu verhindern.

Ich sehe nichts in dem Code, den Sie geschrieben haben, dass offensichtlich bei Fehler ist, zumindest soweit der Fehlercode Beschreibung geht. Ich frage mich also, ob Sie irgendwo anders etwas tun, was die persistente Speicherdatei direkt beeinflusst (d. H. Die Datei überhaupt berührt, anstatt Core-Data-Aufrufe zum Abrufen/Speichern zu durchlaufen)?

Die Erwähnung des Rollback-Journals in der Fehlercode-Beschreibung lässt mich fragen, ob die Einstellung journal_mode zu TRUNCATE verwandt ist. Wenn ich es wäre, würde ich das entfernen (ich weiß nicht, was es hier erreichen soll) oder es auf DELETE setzen. Zumindest für Testzwecke, jedenfalls in der Hoffnung, das Problem besser zu verstehen.

+0

Tom, danke! Daher wurde journal_mode auf 'DELETE' gesetzt, um das Problem zu lösen. Ich hatte die Option nach Ihrer Antwort entfernt, und das schien das Problem gelöst zu haben. Zu dieser Zeit blieben die neuen Entitäten, die ich der Datenbank hinzugefügt hatte, nur bestehen, wenn ich eine Entität gespeichert hatte, die vor meiner Funktion in der MOM vorhanden war. Ich dachte, das Problem wurde gelöst und es war etwas anderes, was ich tat, aber heute habe ich die Option hinzugefügt und es auf DELETE gesetzt und das schien es zu tun. Vielen Dank! Jetzt zu erforschen, warum ... – Randoramma

Verwandte Themen