Estoy lanzando esto como respuesta, aunque en realidad es más un adorno para el fragmento de Charles. La salida directa de NSLog puede ser un desastre para leer e interpretar, por lo que me gusta agregar un poco de espacio en blanco y llamar el valor de algunas claves críticas de 'userInfo'.
Aquí hay una versión del método que he estado usando. ('_sharedManagedObjectContext' es un #define para '[[[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;
}
Esto me permite ver el valor de 'NSValidationErrorKey', que, cuando encontré el problema desde el OP, apuntó directamente a las entidades de datos centrales no opcionales que había olvidado configurar antes de intentar guardar.