One thing I've always had trouble with in Cocoa Bindings has been error presentation, for example when the user types the wrong value into a text field with a formatter attached. Normally I would override willPresentError:
somewhere in the responder chain, but my problem is the NSError objects created by the Bindings system doesn't contain enough information for me to tell what failed, or if it's even an error I'm interested in customizing. I could completely remove bindings from the equation and create my own errors when validation problems occur, but I feel like I would be throwing out some useful stuff that way.
I've been able to get around this by implementing the NSControl delegate methods and storing the control that failed in an instance variable in my view controller. If it's non-nil by the time willPresentError:
rolls around, I know what failed to validate.
- (BOOL)control:(NSControl *)control didFailToFormatString:(NSString *)string errorDescription:(NSString *)error;
{
_errorSender = [control retain];
return NO;
}
- (NSError *)willPresentError:(NSError *)error;
{
if ( _errorSender != nil )
{
NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:[error userInfo]];
NSString *help = NSLocalizedString( @"Why are you always messing up? You are a terrible person.", @"" );
[_errorSender release];
_errorSender = nil;
[userInfo setObject:help forKey:NSLocalizedRecoverySuggestionErrorKey];
return [NSError errorWithDomain:[error domain] code:[error code] userInfo:userInfo];
}
return [super willPresentError:error];
}
This works when the first responder changes, but not when I call commitEditing
on the view controller, so it's only partially useful to me.
The only other option I can see is taking NSFormatter out of the equation, and using validateValue:forKey:error:
in my Core Data managed objects to handle validation. This doesn't make as much sense to me as using a formatter, but at least I'd have full control over the NSError object.
I feel like I must be missing something for there to be this kind of disconnect with error handling. Any suggestions?