Channels ▼


Handling Errors in iOS and OS X with Cocoa

Dispatching the Error

The error object is dispatched by placing it on the responder chain. Each Cocoa application creates the chain at launch time using the NSResponder class (Figure 2).

Figure 2: The responder chain.

The chain manages and routes every user event that occurs. It stays valid for the lifetime of the session; afterwards it gets disposed of by the application. As a rule, only one responder chain can be active per application.

Figure 3 shows how the error object travels along the responder chain (shown as a solid red line). This example shows an application with a document-based design, displaying a single window view.

Figure 3: How en error travels the responder chain.

Here, the NSWindowController object dispatches an error object to the chain. NSDocument then tries to respond to the error. If it can not, it can return the error object or dispatch a new one in its place. NSDocumentController tries to respond next. Again, it can either return the error to the chain or provide its own. Last to respond will be NSApplication. NSApplication may pass the error to its delegate, or it may handle the error itself. In the latter case, its default behavior is to report the error with a modal dialog.

Note that the NSWindow object did not respond to the error due to being downstream on the responder chain. Also, if this was an iOS application, the NSApplication object would be replaced with UIApplication.

Figure 4 shows the three NSResponder methods that let an ObjC object dispatch its error objects. The method presentError: gets an NSError object (anErr) as input and returns a BOOL for a result. Use this for errors that may affect the application as a whole.

Figure 4: NSResponder methods.

The method presentError:modalForWindow:delegate:didPresentSelector:contextInfo: gets four more inputs, in addition to NSError. The second input is the document window view (aWin), the third the delegate object (aRef) that will handle the error. Fourth input is the ObjC routine (aSub); the fifth is a generic pointer to the argument block for that routine (anArgs). Use this method for errors that only affect the current document.

The third NSResponder method willPresentError: gets an NSError as input and returns an NSError as a result. Use this one to examine the error, to resend it, or to send a different error.

Listing Three shows how to dispatch the error object. This ObjC action method gets an object pointer (aSrc) as input. The method starts by creating an instance of NSFileManager (line 9). It prepares a path to the target file (lines 12-14) and sends a removeItemPath:error: message to the instance (line 15). If NSFileManager returns a YES, the action method continues with the rest of its tasks. If NSFileManager returns a NO, the method dispatches the NSError object (tErr) using presentError:. Note the NSFileManager instance gets the object pointer to the tErr object as one of its inputs.

Listing Three

- (IBAction)fooDelete:(id)aSrc
	NSFileManager *tMgr;
	NSString *tPth;
	NSError *tErr;
	NSMutableDictionary *tInf;
	BOOL tChk;
	tMgr = [NSFileManager defaultManager];
	if (tMgr != nil)
		tPth = [NSString 
		tPth = [tPth stringByExpandingTildeInPath];
		tChk = [tMgr removeItemAtPath:tPth error:&tErr];
		if (tChk)
			// do something after deletion...
			[self presentError:tErr];

However, not all Cocoa classes can use the responder chain. Core Data classes, for instance, cannot dispatch their errors to the chain. The same is true for many of the classes from the Foundation Kit framework. As a rule, only classes that derive from NSResponder can access the chain. The NSDocument class also has access, even though it does not derive from NSResponder.

Check the official Apple docs for those Cocoa classes with NSResponder support.

Responding to the Error

The Cocoa application also uses the same three NSResponder methods to respond to the error object. It can respond to the error in four ways. It could report the error using a modal alert dialog. It could record the error to a log file, then resume operation assuming the error is non-fatal. It could dispatch a new, and perhaps more relevant, error object. Or it could simply do the recovery task without involving the user.

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.