macdevcenter.com
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Understanding Exceptions and Handlers in Cocoa
Pages: 1, 2, 3, 4, 5, 6, 7

Listing 11 is an example of the second nesting structure. The two methods, demoA and demoB, have their own exception handlers. Also, the @try block in the method demoA calls the method demoB.

This type of nesting is usually a result of subclassing. A subclass may have a method in its @implementation block calling a method from the parent class. If the parent method has an exception handler, that handler is not nested when the method call is outside the subclass's @try…@catch. But if the method call is within the latter's @try…@catch block, then the parent's handler is nested in the subclass's handler.

Listing 11. Handlers nested in different methods
- (void) demoA
{
    // ...
    // code before the handler
    // ...
    // start of the outer handler
    @try
    {
        // ...
        // code that could generate an outer exception
        // ...
        [self demoB];
        // ...
    }
    @catch (NSException * theErr1)
    {
        // identify the exception
        if ([[theErr1 name] isEqualToString:@"Outer Error"])
            // ...
            // code to handle the outer exception
            // ...
            else
                [theErr1 raise];
    }
    @finally
    {
        // ...
        // finish the outer handler
        // ...
    }
    // ...
}

- (void)demoB
{
    // ...
    // code before the handler
    // ...
    // start of the inner handler
    @try
    {
        // ...
        // code that could generate an inner exception
        // ...
    }
    @catch (NSException * theErr2)
    {
        // identify the exception
        if ([[theErr2 name] isEqualToString:@"Inner Error"])
            // ...
            // code to handle an inner exception
            // ...
            else
                [theErr2 raise];
    }
    @finally
    {
        // ...
        // finish the inner handler
        // ...
    }
    // ...
}

Listing 12 is an example of the third nesting structure. This example shows two classes, DemoOne and DemoTwo. The instance method, demoMethod, in each class has it own @try…@catch…@finally block. Also, the @try block in DemoOne's demoMethod calls the demoMethod in DemoTwo.

This type of nesting is often the result of composition. A Cocoa class that uses other Cocoa classes in its methods may find its handlers nested around handlers from other classes.

Listing 12. Handlers nested in different classes
@implementation DemoOne
- (void)demoMethod
{
    DemoTwo *theClass;
    // ...
    // code before the handler
    // ...
    // start of the level 1 handler
    @try
    {
        // ...
        // code that could generate a level 1 exception
        // ...
        [theClass demoMethod];
    }
    @catch (NSException *theErr)
    {
        // identify the exception
        if ([[theErr name] isEqualToString:@"Outer Error"])
            // ...
            // code to handle a level 1 exception
            // ...
            else
                [theErr raise];
    }
    @finally
    {
        // ...
        // finish the level 1 handler
        // ...
    }
}
@end

@implementation DemoTwo
- (void)demoMethod
{
    // ...
    // code before the handler
    // ...
    // start of the level 2 handler
    @try
    {
        // ...
        // code that could generate a level 2 exception
        // ...
    }
    @catch (NSException *theErr)
    {
        // identify the exception
        if ([[theErr name] isEqualToString:@"Inner Error"])
            // ...
            // code to handle a level 2 exception
            // ...
            else
                [theErr raise];
    }
    @finally
    {
        // ...
        // finish the level 2 handler
        // ...
    }
}
@end

The Flow of Control

Figure 6 shows the basic flow of control for two nested handlers. This flow remains the same regardless of the type of nesting structure. It also scales well for structures with more than two nested handlers.

Control flow within two nested traps.
Figure 6. Control flow within two nested traps

In the example above, the @try block in the outer handler transfers control to the inner handler (green). Then the @try block in the inner handler raises an exception. This exception is first trapped by the @catch block in the same handler (red). After that block handles the exception, it transfers control to the @finally block of the inner handler. Then the inner handler transfers control to the @finally block of the outer handler.

If the inner handler fails to handle the exception, it sends the latter to the outer handler (grey). The @catch block of the outer handler traps the exception and tries to handle it. When it does, it transfers control to the @finally block (blue). Otherwise, it sends the exception to the next possible handler (grey). But the @catch block still transfers control to the @finally block before sending the uncaught exception on its way.

Now when the @try block in the outer handler raises an exception, the flow of control (blue) is the same as that of a single handler. Since the exception occurs before or after the call to the inner handler, control is never transferred to the latter.

Pages: 1, 2, 3, 4, 5, 6, 7

Next Pagearrow