webentwicklung-frage-antwort-db.com.de

iphone Kerndaten Fehler beim Speichern behoben

Ich bekomme eine merkwürdige Fehlermeldung aus den Kerndaten, wenn ich versuche, Zu speichern, aber das Problem, dass der Fehler nicht reproduzierbar ist (er erscheint zu unterschiedlichen Zeiten, wenn verschiedene Aufgaben ausgeführt werden).

die Fehlermeldung:

Unresolved error Domain=NSCocoaErrorDomain Code=1560 UserInfo=0x14f5480 "Operation could not be completed. (Cocoa error 1560.)", {
NSDetailedErrors = (
Error Domain=NSCocoaErrorDomain Code=1570 UserInfo=0x5406d70 "Operation could not be completed. (Cocoa error 1570.)",
Error Domain=NSCocoaErrorDomain Code=1570 UserInfo=0x14f9be0 "Operation could not be completed. (Cocoa error 1570.)"
);
}

die Methode, die den Fehler generiert, lautet:

- (IBAction)saveAction:(id)sender {
    NSError *error;
    if (![[self managedObjectContext] save:&error]) {
        // Handle error
        NSLog(@"Unresolved error %@, %@, %@", error, [error userInfo],[error localizedDescription]);
        exit(-1);  // Fail
    }
}

eine Idee für den Grund dieser Nachricht? geben, dass es zu zufälligen Zeiten erscheint 

168
Ahmed Kotb

Dies bedeutet, dass eine obligatorische Eigenschaft mit Null belegt wurde. Aktivieren Sie in Ihrem * .xcodatamodel das Kontrollkästchen "optional" oder stellen Sie beim Speichern in managedObjectContext sicher, dass Ihre Eigenschaften ausgefüllt sind. 

Wenn Sie nach dem Ändern des Codes an die beiden Anforderungen weitere Fehler erhalten, reinigen Sie Ihren Build und löschen Sie die Anwendung von Ihrem iPhone Simulator/iPhone-Gerät. Ihre Modelländerung kann mit der alten Modellimplementierung in Konflikt stehen.

Bearbeiten:

Ich habe fast vergessen, dass hier alle Fehlercodes ausgegeben werden, die Core Data ausspuckt: Core Data Constants Reference Ich hatte zuvor Probleme damit und erkannte, dass das Kontrollkästchen deaktiviert wurde. Solche Schwierigkeiten, das Problem herauszufinden. Viel Glück.

291
David Wong

Ich hatte selbst eine Weile mit mir zu kämpfen. Das eigentliche Problem hier ist, dass das Debuggen, das Sie haben, Ihnen nicht zeigt, was das Problem ist. Der Grund dafür ist, dass CoreData ein Array von NSError-Objekten in das NSError-Objekt "oberste Ebene" einfügt, das bei mehr als einem Problem zurückgegeben wird 1570er Jahre). Es scheint, dass CoreData über eine Handvoll Schlüssel verfügt, um Informationen in dem zurückgegebenen Fehler zu speichern, wenn ein Problem auftritt, das nützliche Informationen liefert (z. B. die Entität, auf der der Fehler auftrat, die fehlende Beziehung/das Attribut usw.) ). Die Schlüssel, die Sie zur Überprüfung des userInfo-Wörterbuchs verwenden, finden Sie in den Referenzdokumenten hier .

Dies ist der Codeblock, den ich verwende, um eine vernünftige Ausgabe des Fehlers zu erhalten, der beim Speichern zurückgegeben wird:

    NSError* error;
    if(![[survey managedObjectContext] save:&error]) {
        NSLog(@"Failed to save to data store: %@", [error localizedDescription]);
        NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
        if(detailedErrors != nil && [detailedErrors count] > 0) {
            for(NSError* detailedError in detailedErrors) {
                NSLog(@"  DetailedError: %@", [detailedError userInfo]);
            }
        }
        else {
            NSLog(@"  %@", [error userInfo]);
        }
    }

Sie erhalten eine Ausgabe mit Informationen zu den fehlenden Feldern, wodurch die Behebung des Problems erheblich vereinfacht wird.

232
Charles

Ich füge dies als Antwort hinzu, auch wenn es wirklich eher eine Verschönerung von Charles 'Ausschnitt ist. Die direkte Ausgabe von NSLog kann ein Durcheinander zum Lesen und Interpretieren sein. Ich ziehe also gerne etwas Leerzeichen ein und nenne den Wert einiger kritischer "userInfo" -Tasten.

Hier ist eine Version der Methode, die ich verwendet habe. ('_sharedManagedObjectContext' ist ein #define für '[[[UIApplication sharedApplication] delegate] managedObjectContext].)

- (BOOL)saveData {
    NSError *error;
    if (![_sharedManagedObjectContext save:&error]) {
        // If Cocoa generated the error...
        if ([[error domain] isEqualToString:@"NSCocoaErrorDomain"]) {
            // ...check whether there's an NSDetailedErrors array            
            NSDictionary *userInfo = [error userInfo];
            if ([userInfo valueForKey:@"NSDetailedErrors"] != nil) {
                // ...and loop through the array, if so.
                NSArray *errors = [userInfo valueForKey:@"NSDetailedErrors"];
                for (NSError *anError in errors) {

                    NSDictionary *subUserInfo = [anError userInfo];
                    subUserInfo = [anError userInfo];
                    // Granted, this indents the NSValidation keys rather a lot
                    // ...but it's a small loss to keep the code more readable.
                    NSLog(@"Core Data Save Error\n\n \
                      NSValidationErrorKey\n%@\n\n \
                      NSValidationErrorPredicate\n%@\n\n \
                      NSValidationErrorObject\n%@\n\n \
                      NSLocalizedDescription\n%@", 
                      [subUserInfo valueForKey:@"NSValidationErrorKey"], 
                      [subUserInfo valueForKey:@"NSValidationErrorPredicate"], 
                      [subUserInfo valueForKey:@"NSValidationErrorObject"], 
                      [subUserInfo valueForKey:@"NSLocalizedDescription"]);
                }
            }
            // If there was no NSDetailedErrors array, print values directly
            // from the top-level userInfo object. (Hint: all of these keys
            // will have null values when you've got multiple errors sitting
            // behind the NSDetailedErrors key.
            else {
                    NSLog(@"Core Data Save Error\n\n \
                      NSValidationErrorKey\n%@\n\n \
                      NSValidationErrorPredicate\n%@\n\n \
                      NSValidationErrorObject\n%@\n\n \
                      NSLocalizedDescription\n%@", 
                      [userInfo valueForKey:@"NSValidationErrorKey"], 
                      [userInfo valueForKey:@"NSValidationErrorPredicate"], 
                      [userInfo valueForKey:@"NSValidationErrorObject"], 
                      [userInfo valueForKey:@"NSLocalizedDescription"]);

            }
        } 
        // Handle mine--or 3rd party-generated--errors
        else {
            NSLog(@"Custom Error: %@", [error localizedDescription]);
        }
        return NO;
    }
    return YES;
}

Dadurch kann ich den Wert für 'NSValidationErrorKey' sehen, der, als ich auf das Problem aus dem OP stieß, direkt auf die nicht optionalen Core Data-Entitäten verwies, die ich vor dem Speichern vergessen hatte.

21
clozach

Es hat mir geholfen. Überprüfen Sie dies auch.

Aktivieren Sie das Kontrollkästchen optional in Ihren * .xcodatamodel-Objekten

0
ssowri1

Ich hatte eine vorübergehende Eigenschaft vom Typ int, die nicht optional war. Wenn es auf 0 gesetzt wurde, wird offensichtlich ein Fehler von 1570 angezeigt. Ich habe einfach alle meine vorübergehenden Eigenschaften in optional geändert. Bei Bedarf kann eine Nullprüfungslogik im Code implementiert werden.

0

Ich meine, Ihr Modell konnte nicht validiert werden, was aus verschiedenen Gründen geschehen kann: ungenutztes Eigentum in Ihrem Modell, fehlender Wert, der als erforderlich markiert ist .. Um ein besseres Verständnis für die Fehler zu erhalten, setzen Sie einen Haltepunkt in ein Platzieren Sie sich an dem Ort, an dem Sie Ihr Objekt speichern möchten, und rufen Sie eine der validateFor...-Methodenvarianten auf, z.

po [myObject validateForInsert]

Ausführlichere Informationen zum Problem finden Sie in der Fehlerbeschreibung. Eine erfolgreiche Validierung bedeutet, dass Sie keine Ausgabe erhalten. 

0
kkodev

Das Problem hat mich berührt, als ich den zweiten Datensatz in CoreData speichere. Alle nicht optionalen Felder (Beziehung) wurden auch ohne Null gefüllt, aber in der Fehlerausgabe würde ich feststellen, dass eines der Felder im ersten gespeicherten Objekt zu Null wurde. Seltsam ein bisschen? Aber der Grund ist ziemlich trivial - eine Eins-zu-Eins-Beziehung, die das erste Objekt zunichte macht, wenn ich es im zweiten setze.

Das Schema ist also:

"Parent" with relationship "child" One to One
Create Child 1, set parent. Save - OK
Create Child 2, set parent. Save - Error, Child 1.Parent == nil
(behind the scene child 2 did nullify child 1 parent)

Durch das Ändern der Beziehung in "Übergeordnet" von "Eins zu Eins zu Viele zu Eins" wurde diese Aufgabe gelöst.

0
HotJard