Listing Four describes how an application-wide error gets displayed with an alert dialog. Here, presentError: starts by identifying the error (line 6). If the error is NSFileNoSuchFileError (id = 4), presentError: uses the factory alertWithError: to create an NSAlert instance (line 13). It then displays the dialog view with a runModal message (line 14). For document-specific errors, use beginSheetModalForWindow:modalDelegate:... to display the dialog view.
Listing Four
- (BOOL) presentError:(NSError *)anErr
{
NSInteger *eID;
// identify the error
eID = [anErr code];
switch (eID)
{
case NSFileNoSuchFileError:
NSAlert *tDlg;
// display the error alert
tDlg = [NSAlert alertWithError:anErr];
[tDlg runModal];
break;
default:
NSString *eType, *eDesc, *eFail;
NSString *eFrmt;
// extract the key error data
eType = [anErr domain];
eDesc = [anErr localizedDescription];
eFail = [anErr localizedFailureReason];
// record the data
eFrmt = [NSString stringWithString:@"Error=%d, domain=%@,
description=%@, reason=%@"];
NSLog (eFrmt, eID, eType, eDesc, eFail);
}
}
Figure 5 shows how the NSAlert dialog view presents the strings from the support dictionary. The localizedDescription string (NSLocalizedDescriptionKey) becomes the dialog's main message. The localizedRecoverySuggestion string (NSLocalizedRecoverySuggestionErrorKey) appears as a subtitle underneath the main message. The strings from the localizedRecoveryOptions array (NSLocalizedRecoveryOptionsErrorKey) show up as button labels, arranged from a right to left direction. The right-most button gets the zeroth string, the next button the first string, and so on. If localizedRecoveryOptions returns a nil object, NSAlert displays a single OK button. Note the localizedFailureReason string does not appear on the dialog view.
Figure 5: How the NSAlert dialog view presents the strings from the support dictionary.
Listing Four also describes how the error object gets saved to a log file. If the error is not NSFileNoSuchFileError, presentError: reads off the error data using the four accessors (line 22-24). It prepares a format string (line 27) and uses NSLog to format and emit the error data (line 28). This adds the formatted string into the file /private/var/log/asl.db on OS X 10.5 (Leopard) and newer. To view the log entries, use the Console utility application.
Listing Five shows how presentError: might display the error object from within an iOS application. Again, the method reads three data items from the NSError object (lines 9-11). Then it combines those items into a formatted NSString object (lines 14-19). Next, presentError: creates an instance of UIAlertView (lines 22-25). It sets the dialog's title and message, then sends a show message to display the dialog view (line 28). After the user interacts with the dialog, presentView: disposes of the view with a release message (line 29).
Listing Five
- (BOOL) presentError:(NSError *)anErr
{
NSString *eDesc, *eFail;
NSString *eTitl, *eMesg;
NSInteger *eID;
UIAlertView *tDlg;
// extract the key error data
eID = [anErr code];
eDesc = [anErr localizedDescription];
eFail = [anErr localizedFailureReason];
// format the error data
eTitl = [NSString stringWithString:@"Error %d"];
eTitl = [NSString stringWithFormat:eTitl, eID];
eMesg = [NSString stringWithString:@"%@\n%@"];
eMesg = [NSString stringWithFormat:eMesg,
eDesc, eFail];
// create the dialog view
tDlg = [[UIAlertView alloc]
initWithTitle:eTitl message:eMesg
delegate:nil cancelButtonTitle:@"OK"
otherButtonTitles:nil];
// display the view
[tDlg show];
[tDlg release];
// perform post-error tasks
}
Listing Six describes how willPresentError: would process the error object. It starts by identifying the error (line 18). For the NSFileReadUnknownError, willPresentError: prepares a new error object with a different ID, domain, and dictionary (lines 23-36). For the NSUserCancelledError object, it prepares another error object, one without a support dictionary (line 41-42). For all other errors, willPresentError: returns the error object unchanged (line 47).
Listing Six
// Declare the following constants
const NSString *FooErrDomain;
enum FooErrCodes;
{
FooFileReadFail = 0xf411,
FooUserCancel = 0xc4c31
};
//...
- (NSError *)willPresentError:(NSError *)anErr
{
NSString *eDesc, *eFail;
NSMutableDictionary *eData;
NSError *eErr;
// identify the error
eID = [anErr code];
switch (eID)
{
case NSFileReadUnknownError:
// prepare the error message strings
eDesc = [NSString stringWithString:@"Unable to read data from the document file."];
eFail = [NSString stringWithString:@"File is either locked or missing."];
// prepare the support dictionary
eData = [NSMutableDictionary
dictionaryWithCapacity:2];
[eData setObject:eDesc
forKey:NSLocalizedDescriptionKey];
[eData setObject:eFail
forKey:NSLocalizedFailureReasonErrorKey];
// create a new error
eErr = [NSError errorWithDomain:FooErrDomain
code:FooFileReadFail userInfo:eData];
break;
case NSUserCancelledError:
// create the new error
eErr = [NSError errorWithDomain:FooErrDomain
code:FooUserCancel userInfo:nil];
break;
default:
// pass the original error
eErr = anErr;
break;
}
// return the modified error
return (eErr);
}
Recovering from Errors
As pointed out earlier, one entry in the NSError support dictionary is the recovery object. This object performs whatever task is needed to correct the reported error. It runs right after users interact with the alert dialog, and it implements the informal protocol NSErrorRecoveryAttempting.


