AWS Mobile Blog

How Not to Throw Exceptions with the AWS SDK for iOS

by Yosuke Matsuda | on | Permalink | Comments |  Share

Version 2 of the AWS Mobile SDK

  • This article and sample apply to Version 1 of the AWS Mobile SDK. If you are building new apps, we recommend you use Version 2. For details, please visit the AWS Mobile SDK page.
  • This content is being maintained for historical reference.

Whenever early versions of the AWS SDK for iOS encountered an error, they threw either an AmazonServerException or an AmazonClientException. This forced developers to surround any AWS-related code with @try/@catch blocks. This was not intuitive for many Objective-C developers and is not the recommended way to handle error conditions in the Cocoa Framework. Starting with the AWS SDK for iOS version 1.4.0, we introduced a new option to return NSError objects instead of throwing exceptions.

Turning Off the Exceptions

You can enable this option by importing AmazonErrorHandler.h and calling [AmazonErrorHandler shouldNotThrowExceptions]. We recommend that you make this call in the application:didFinishLaunchingWithOptions: application delegate method. Once this method is invoked, the error property in the AmazonResponse object contains an NSError object for any failed calls to AWS.

#import "AppDelegate.h"
#import <AWSiOSSDK/AmazonErrorHandler.h>

@implementation AppDelegate

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    ...
    [AmazonErrorHandler shouldNotThrowExceptions];
    ...

Handling the Errors

Always confirm that the error property is nil before continuing.

S3GetObjectRequest  *getObjectRequest  = [[[S3GetObjectRequest alloc] initWithKey:YOUR_OBJECT_KEY withBucket:YOUR_BUCKET_NAME] autorelease];
S3GetObjectResponse *getObjectResponse = [s3Client getObject:getObjectRequest];
if(getObjectResponse.error != nil)
{
    NSLog(@"Error: %@", getObjectResponse.error);
    return;
}

// Do something with getObjectResponse.

For asynchronous calls with AmazonServiceRequestDelegate, the request:didFailWithError: delegate method is called instead of request:didFailWithServiceException:. Only one delegate method will be called in the case of error, never both. The delegate method called will match the kind of error behavior you desire: exceptions or errors.

-(void)request:(AmazonServiceRequest *)request didFailWithError:(NSError *)theError
{
    // Do something with theError.
}

-(void)request:(AmazonServiceRequest *)request didFailWithServiceException:(AmazonServiceException *)theException
{
    // This delegate method won't be called anymore. You can remove this delegate method from your apps.
}

Keeping the Exceptions

Today, the default behavior of the AWS SDK for iOS is to throw exceptions, but we plan to make NSError the default behavior in a future SDK release. If you prefer exceptions, and if you want to ensure that your current code continues to work even after the default behavior changes, call [AmazonErrorHandler shouldThrowExceptions] like so:

#import "AppDelegate.h"
#import <AWSiOSSDK/AmazonErrorHandler.h>

@implementation AppDelegate

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    ...
    [AmazonErrorHandler shouldThrowExceptions];
    ...

All of our sample apps now use errors, so please take a look at any of our new samples for the details on how to handle errors.

As always, please let us know if you have any questions.