Brief Intro to NSException of Foundation Framework

NSException

The NSException class supports exception management. Its methods provide functionality for creating NSException instances, querying an instance, raising exceptions, and retrieving exception stack frames. The following statement uses the exceptionWithName:reason:userInfo: factory method to create an NSException object.

NSException *exception = [NSException exceptionWithName:NSGenericException
                                                 reason:@"Test exception"
                                               userInfo:nil];

The parameters for this method are the name of the exception (exceptionWithName:), the reason for the exception (reason:), and a dictionary (userInfo:) containing user-defined information relating to the exception. In the preceding example, the exception name is NSGenericException, one of the Foundation Constants general exception names. Listing 14-9 creates and raises an exception using the raise:format: class method. This exception is caught and handled within the body of the corresponding @catch() block.

Listing 14-9.  Creating and Raising an NSException Instance

@try
{
  [NSException raise:NSGenericException format:@"My Generic Exception"];
}
@catch (NSException *exception)
{
  NSLog(@"EXCEPTION\nName-> %@\nDescription-> %@", [exception name],
        [exception description]);
}

Listing 14-9 shows the argument to the @catch() directive is an NSException object, the exception raised in the corresponding exception-handling domain. Exceptions can also be nested, thereby enabling an exception to be processed by the local exception handler domain and any surrounding handlers. Listing 14-10 modifies the example shown in Listing 14-9 to demonstrate the use of nested exception handlers.

Listing 14-10.  Nested Exception Handlers

@try
{
  @try
  {
    [NSException raise:NSGenericException format:@"My Generic Exception"];
  }
  @catch (NSException *exception)
  {
    NSLog(@"EXCEPTION handling in domain 2\nName-> %@\nDescription-> %@",
          [exception name], [exception description]);
    @throw;
  }
  @finally
  {
    NSLog(@"Cleanup for exception domain 2");
  }
}
@catch (NSException *exception)
{
  NSLog(@"EXCEPTION handling in domain 1\nName-> %@\nDescription-> %@",
        [exception name], [exception description]);
}
@finally
{
  NSLog(@"Cleanup for exception domain 1");
}

If an exception is not caught by your code, it is caught by the uncaught exception handler function. The default implementation of this function logs a message to the output pane, and then exits the program. The Foundation function NSSetUncaughtExceptionHandler() can be used to set a custom uncaught exception handler.

Exceptions and Memory Management

Memory management must be carefully considered when handling exceptions, particularly when using Manual Retain Release (MRR) memory management. As exception processing changes program flow control, Listing 14-11 demonstrates how an exception in a method (when using MRR memory management) may cause an object to leak memory.

Listing 14-11.  Exception Handling and Memory Leaks

- (void) processOrderWithItem:(OrderItem *)item
{
  Order *order = [[Order alloc] initWithItem:item];
  [order process];
  [order release];
}

If the process method throws an exception, the Order object will not be released, and hence it leaks memory. To prevent this, the solution is to enclose the method statements within an exception-handling domain and to release the allocated object within its @finally block, as shown in Listing 14-12.

Listing 14-12.  Preventing Memory Leaks with an Exception Handling Domain

- (void) processOrderWithItem:(OrderItem *)item
{
  Order *order = nil;
  @try
  {
    order = [[Order alloc] initWithItem:item];
    [order process];
    [order release];
  }
  @finally
  {
    [order release];
  }
}

By default, ARC memory management is not exception-safe. A program using ARC can be made exception-safe if it is compiled with the -fobjc-arc-exceptions option. This will increase program resource utilization and also slightly decrease performance, and hence its use must be carefully considered.

Performing Exception Handling

Now you will create a program that demonstrates exception handling for a Foundation Framework object. In Xcode, create a new project by selecting New Project . . . from the Xcode File menu. In the New Project Assistant pane, create a command-line application. In the Project Optionswindow, specify XProcessor for the Product Name, choose Foundation for the Project Type, and select ARC memory management by selecting the Use Automatic Reference Counting check box. Specify the location in your file system where you want the project to be created (if necessary selectNew Folder and enter the name and location for the folder), uncheck the Source Control check box, and then click the Create button.

In the Xcode project navigator, select the main.m file and update the main() function, as shown inListing 14-13.

Listing 14-13.  XProcessor main( ) Function Implementation

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
  @autoreleasepool
  {
    NSArray *words = @[@"Hello", @"Bonjour", @"Guten Tag", @"Hola"];
    @try
    {
      int count = 0;
      NSLog(@"Salutation = %@", words[count]);
    }
    @catch (NSException *exception)
    {
      NSLog(@"EXCEPTION\nName-> %@\nDescription-> %@", [exception name],
            [exception description]);
    }
  }
  return 0;
}

The main() function first creates an NSArray object with four entries. Then an entry from the array is retrieved and logged to the output pane. Because the NSArray method for retrieving an object at a specified index will throw an NSRangeException (one of the Foundation standard exception names) if the index is beyond the end of the array, this statement is placed within an exception-handling domain. If an exception is thrown, it is logged to the output pane.

Now save, compile, and run the XProcessor program and observe that the expected message (Hello) is displayed in the output pane (as shown in Figure 14-3).

9781430250500_Fig14-03.jpg

Figure 14-3Testing the XProcessor project, no exception raised

No exception was thrown because the value set for the index was within range. Now change the value for the count variable to four.

int index = 0;

Then recompile and run the program. Observe that because the index exceeded the range, an exception was thrown and handled within the @catch() block (as shown in Figure 14-4).

9781430250500_Fig14-04.jpg

Figure 14-4Testing the XProcessor project, exception raised

This example demonstrates exception handling for Foundation Framework APIs. Let’s continue on with the Foundation constants that define a set of standard exception names.



Foundation Standard Exception Names

The Foundation Framework defines a set of standard exception names. These general exception names are listed and described in Table 14-2.

Table 14-2Foundation Constants General Exception Names

Exception Name Description
NSGenericExceptionA generic name for an exception.
NSRangeExceptionAn exception that occurs when attempting access outside the bounds of some data, such as an array or a string.
NSInvalidArgumentExceptionAn exception that occurs when you pass an invalid argument to a method.
NSInternalInconsistencyExceptionAn exception that occurs when an internal assertion fails (e.g., via an NSAssert function) and implies an unexpected condition in code.
NSObjectInaccessibleExceptionAn exception that occurs when a remote object is accessed from a thread that should not access it.
NSObjectNotAvailableExceptionA distributed object exception that occurs when the remote side of the NSConnection refuses to send a message to the object because it has not been vended.
NSDestinationInvalidExceptionA distributed object exception that occurs when an internal assertion fails.
NSPortTimeoutExceptionA timeout set on a port that expires during a send or receive operation.
NSInvalidSendPortExceptionThe send port of an NSConnection object has become invalid.
NSInvalidRecievePortExceptionThe receive port of an NSConnection object has become invalid.
NSPortSendExceptionAn NSPort-specific generic error that occurs when sending a message to a port.
NSPortReceiveExceptionAn NSPort-specific generic error that occurs when receiving a message from a port.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值