Showing posts with label More iPhone 3 Development. Show all posts
Showing posts with label More iPhone 3 Development. Show all posts

Tuesday, March 30, 2010

Another SuperDB Validation Tweak

In ManagedObjectAttributeEditor.m, there is this method:

...
#pragma mark -
#pragma mark Alert View Delegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == [alertView cancelButtonIndex]) {
[self.managedObject.managedObjectContext rollback];
[self.navigationController popViewControllerAnimated:YES];
}

}

@end

Now, if you say you're going to fix, and then don't, the context never gets rolled back. It should really be:
...
#pragma mark -
#pragma mark Alert View Delegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
[self.managedObject.managedObjectContext rollback];
if (buttonIndex == [alertView cancelButtonIndex]) {
[self.navigationController popViewControllerAnimated:YES];
}

}

@end

Since we don't have bindings, the incorrect value shown in the GUI will stay there, we're just removing it from the context. When they hit Save again, we'll copy the value back into the context, but if they hit cancel, we won't leave an invalid value sitting in the unsaved context.

Monday, March 29, 2010

Well, That's Embarrassing…

In the SuperDB application in More iPhone 3 Development, when we added multi-attribute validation, we inadvertently stopped the single-field validation on birthdate to stop working. In Hero.m, we have this at the end:

...
- (BOOL)validateForInsert:(NSError **)outError {
return [self validateNameOrSecretIdentity:outError];
}

- (BOOL) validateForUpdate:(NSError **)outError {
return [self validateNameOrSecretIdentity:outError];
}

@end

The method validateNameOrSecretIdentity: does our cross-field validation by looking at the two fields, but it doesn't do the rest of the validations, such as those from the data model, or those from custom validation methods. To handle those, we need a call to super.

The easiest way to handle this is to simply call super if validateNameOrSecretIdentity: returns NO. Typically, once we hit an error, we don't keep going. We could implement a more complex version that kept a running track of all errors and returned them, but I'm going to keep things simple here. Replace the code above with the following to get the rest of the validations working again:

...
- (BOOL)validateForInsert:(NSError **)outError {
BOOL validated = [self validateNameOrSecretIdentity:outError];
if (!validated)
return validated;
return [super validateForInsert:outError];
}

- (BOOL)validateForUpdate:(NSError **)outError {
BOOL validated = [self validateNameOrSecretIdentity:outError];
if (!validated)
return validated;
return [super validateForUpdate:outError];
}

@end

I apologize for that!