Returning a useful error from NSDocument's -readFromURL:...
Returning a useful error from NSDocument's -readFromURL:...
- Subject: Returning a useful error from NSDocument's -readFromURL:...
- From: Keith Blount <email@hidden>
- Date: Wed, 3 Mar 2010 13:52:56 -0800 (PST)
Hello,
Okay, I know this comes up a lot, but I can't find a single page with a satisfactory solution. Please feel free to post nothing but a link with the solution if I have missed the bloomin’ obvious, of course - this question has been asked here before and in other places, and it seems as though it should be simple, but nothing I try is entirely satisfactory:
My app overrides NSDocument's -readFromURL:ofType:error: to load its data. For the different circumstances in which the load might fail, I want to present to the user an alert panel explaining the reason for the failure. This, as I understand it, is the entire purpose of NSError, except that in this circumstance it seems to be doing more harm than good and just doesn't work as it should.
First, let's say I want to say to the user, "Invalid XML Data". And underneath that, in smaller, message text, I want it to say something like, "The document cannot be loaded because the XML file contained invalid characters." So, here is my error-setting:
if (outError)
{
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
[userInfo setObject:NSLocalizedString(@"Invalid XML Data", @"") forKey:NSLocalizedDescriptionKey];
[userInfo setObject:NSLocalizedString(@"The document cannot be loaded because the XML file contained invalid characters.",nil) forKey: NSLocalizedFailureReasonErrorKey];
*outError = [NSError errorWithDomain:@"" code:0 userInfo:userInfo];
}
That works okay, except that the failure reason doesn’t get displayed.
I read somewhere that if you want the reason to appear, you have to use NSLocalizedRecoverySuggestionErrorKey instead of NSLocalizedFailureReasonErrorKey, and you have to call -presentError: directly in order for it to appear, and just cancel the error that would normally get displayed. And I’m sure this used to work, too, but it no longer seems to (possibly since 10.6, but I haven’t checked on an earlier system yet).
But even if calling -presentError: did work and I could use it to display the information I want, I would still have to cancel the error that would otherwise get displayed - and there doesn’t seem to be a way of doing this. A perfect solution for me would be to tell NSDocument not to display an error at all, and then I could display my own using NSRunAlertPanel(), adding any title and description I wanted. (Well, not “perfect” - perfect would be getting NSDocument to present a nice error that explains to the user what is wrong rather than keeping the information I give it to itself.)
The documentation clearly states that you can tell NSDocument not to present an error by setting its domain to NSCocoaErrorDomain and its code to NSUserCancelledError:
“he Application Kit presents errors through the NSApplication implementations of the presentError: and presentError:modalForWindow:delegate:didPresentSelector:contextInfo: methods declared by NSResponder. Those implementations silently ignore errors whose domain is NSCocoaErrorDomain and whose code is NSUserCancelledError.”
(This is from the “Error Handling in the Document Architecture” section of the Document-Based Applications Overview: http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/Documents/Articles/ErrorHandling.html)
However, this simply doesn’t work for NSDocument’s -readFromURL:ofType:error: I have tried to set outError as follows:
if (outError)
*outError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSUserCancelledError userInfo:nil];
But that results in an alert panel coming up saying nothing more than “Alert” - it still displays an error panel.
(I have also tried overriding -presentError: - even though the docs say you shouldn’t need to - but it seems this isn’t called in this case, which is unsurprising as the docs do say that NSApplication’s implementation is called.)
What is the correct way of handling this? It’s bad enough that the user has to see an error message at all (although on some occasions it may be used to tell the user that the project needs updating to a newer format, which is more common than genuine errors), without the error messages seeming unprofessional or unforthcoming in the information they provide. Of course, I could put all of the information into NSLocalizedDescriptionKey, but this looks horrible as it’s all in bold, and would then be one stream of text without a title. Really it should have a title telling the user succinctly that there has been an error an then some message text explaining more about the error and possibly what to do about it.
Suggestions/solutions/pointers/RTFM links much appreciated.
Many thanks in advance and all the best,
Keith
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden