Channels ▼
RSS

Mobile

Handling Errors in iOS and OS X with Cocoa


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.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video