84 votes

iPhone de Base de Données "Production" d'Erreur de Manipulation

J'ai vu dans l'exemple de code fourni par Apple références à la façon dont vous devez gérer les Données de Base des erreurs. I. e:

NSError *error = nil;
if (![context save:&error]) {
/*
 Replace this implementation with code to handle the error appropriately.

 abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
 */
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}

Mais jamais aucun des exemples de la façon dont vous devriez la mettre en œuvre.

Quelqu'un aurait-il (ou peut m'indiquer la direction de) quelque peu de la "production" de code qui illustre la méthode ci-dessus.

Merci d'avance, Matt

32voto

Marcus S. Zarra Points 32178

Personne ne va vous montrer le code de production, car elle dépend de 100% sur votre application, et où l'erreur se produit.

Personnellement, j'ai mis une instruction assert là parce que 99,9% du temps, cette erreur va se produire dans le développement et quand vous l'y fixer, il est très peu probable que vous verrez dans la production.

Après l'affirmer, je voudrais présenter une alerte à l'utilisateur, faites-leur savoir qu'une erreur irrécupérable s'est produite et que l'application qui va sortir. Vous pouvez aussi mettre un texte de présentation en y demandant de contacter le développeur de sorte que vous pouvez espérer le suivi de ce fait.

Après cela, je laisse la abort() là aussi il sera le "crash" de l'application et de générer une trace de ce que vous pouvez espérer l'utiliser plus tard pour suivre la question.

32voto

Johannes Fahrenkrug Points 12795

C'est une méthode générique, je suis venu avec pour gérer et afficher les erreurs de validation sur l'iPhone. Mais Marcus est à droite: Vous auriez probablement souhaitez personnaliser les messages pour être plus convivial. Mais au moins vous donne un point de départ pour voir ce champ n'a pas de valider et pourquoi.

- (void)displayValidationError:(NSError *)anError {
    if (anError && [[anError domain] isEqualToString:@"NSCocoaErrorDomain"]) {
        NSArray *errors = nil;

        // multiple errors?
        if ([anError code] == NSValidationMultipleErrorsError) {
            errors = [[anError userInfo] objectForKey:NSDetailedErrorsKey];
        } else {
            errors = [NSArray arrayWithObject:anError];
        }

        if (errors && [errors count] > 0) {
            NSString *messages = @"Reason(s):\n";

            for (NSError * error in errors) {
                NSString *entityName = [[[[error userInfo] objectForKey:@"NSValidationErrorObject"] entity] name];
                NSString *attributeName = [[error userInfo] objectForKey:@"NSValidationErrorKey"];
                NSString *msg;
                switch ([error code]) {
                    case NSManagedObjectValidationError:
                        msg = @"Generic validation error.";
                        break;
                    case NSValidationMissingMandatoryPropertyError:
                        msg = [NSString stringWithFormat:@"The attribute '%@' mustn't be empty.", attributeName];
                        break;
                    case NSValidationRelationshipLacksMinimumCountError:  
                        msg = [NSString stringWithFormat:@"The relationship '%@' doesn't have enough entries.", attributeName];
                        break;
                    case NSValidationRelationshipExceedsMaximumCountError:
                        msg = [NSString stringWithFormat:@"The relationship '%@' has too many entries.", attributeName];
                        break;
                    case NSValidationRelationshipDeniedDeleteError:
                        msg = [NSString stringWithFormat:@"To delete, the relationship '%@' must be empty.", attributeName];
                        break;
                    case NSValidationNumberTooLargeError:                 
                        msg = [NSString stringWithFormat:@"The number of the attribute '%@' is too large.", attributeName];
                        break;
                    case NSValidationNumberTooSmallError:                 
                        msg = [NSString stringWithFormat:@"The number of the attribute '%@' is too small.", attributeName];
                        break;
                    case NSValidationDateTooLateError:                    
                        msg = [NSString stringWithFormat:@"The date of the attribute '%@' is too late.", attributeName];
                        break;
                    case NSValidationDateTooSoonError:                    
                        msg = [NSString stringWithFormat:@"The date of the attribute '%@' is too soon.", attributeName];
                        break;
                    case NSValidationInvalidDateError:                    
                        msg = [NSString stringWithFormat:@"The date of the attribute '%@' is invalid.", attributeName];
                        break;
                    case NSValidationStringTooLongError:      
                        msg = [NSString stringWithFormat:@"The text of the attribute '%@' is too long.", attributeName];
                        break;
                    case NSValidationStringTooShortError:                 
                        msg = [NSString stringWithFormat:@"The text of the attribute '%@' is too short.", attributeName];
                        break;
                    case NSValidationStringPatternMatchingError:          
                        msg = [NSString stringWithFormat:@"The text of the attribute '%@' doesn't match the required pattern.", attributeName];
                        break;
                    default:
                        msg = [NSString stringWithFormat:@"Unknown error (code %i).", [error code]];
                        break;
                }

                messages = [messages stringByAppendingFormat:@"%@%@%@\n", (entityName?:@""),(entityName?@": ":@""),msg];
            }
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Validation Error" 
                                                            message:messages
                                                           delegate:nil 
                                                  cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
            [alert show];
            [alert release];
        }
    }
}

Profitez de.

5voto

cschuff Points 1141

J'ai trouvé cette commune de la fonction enregistrer une bien meilleure solution:

- (BOOL)saveContext {
    NSError *error;
    if (![self.managedObjectContext save:&error]) {
        DDLogError(@"[%@::%@] Whoops, couldn't save managed object context due to errors. Rolling back. Error: %@\n\n", NSStringFromClass([self class]), NSStringFromSelector(_cmd), error);
        [self.managedObjectContext rollback];
        return NO;
    }
    return YES;
}

Chaque fois qu'une sauvegarde échoue, cela annulera votre NSManagedObjectContext signifie qu'elle va réinitialiser toutes les modifications qui ont été effectuées dans le contexte depuis la dernière sauvegarde. Donc, vous devez regarder attentivement pour toujours conserver les modifications effectuées à l'aide de la fonction d'enregistrement plus tôt et régulièrement que possible, car vous pouvez facilement perdre de données.

Pour l'insertion de données, cela peut être un looser variante permettant à d'autres modifications en direct sur:

- (BOOL)saveContext {
    NSError *error;
    if (![self.managedObjectContext save:&error]) {
        DDLogError(@"[%@::%@] Whoops, couldn't save. Removing erroneous object from context. Error: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), object.objectId, error);
        [self.managedObjectContext deleteObject:object];
        return NO;
    }
    return YES;
}

Note: j'utilise CocoaLumberjack pour l'enregistrement ici.

Aucun commentaire sur la façon d'améliorer ce est le bienvenue!

BR Chris

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X