AWS Mobile Blog

Using the AWS SDK for iOS Asynchronously – Part I: Sync vs. Async

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.

The AWS SDK for iOS offers two types of requests: synchronous and asynchronous. When the delegate property of the request object such as S3PutObjectRequest is not set, the request is treated as a synchronous operation, and the client blocks the current thread until it finishes processing the request. When the delegate is set, the request is treated as an asynchronous operation. It returns immediately and does not block the current thread.

How to use AmazonServiceRequestDelegate

Synchronous calls

In the following example, [s3Client putObject:request] blocks the calling thread until it finishes the execution.

#import "YourViewController.h"

@implementation YourViewController

... // Initialize AmazonS3Client.

- (void)putObject
{
    S3PutObjectRequest *request = [[S3PutObjectRequest alloc] initWithKey:objectName.text inBucket:self.bucket];
    request.data = data;

    // Note that request.delegate is not set.

    S3PutObjectResponse *response = [s3Client putObject:request]; // The request blocks the main thread until it completes.
    if(response.error != nil)
    {
        NSLog(@"Error: %@", response.error);
    }   
    ...
}

Asynchronous calls

When the delegate is set, the request immediately returns.

- (void)putObject
{
    S3PutObjectRequest *request = [[S3PutObjectRequest alloc] initWithKey:objectName.text inBucket:self.bucket];
        request.data = data;

    // request.delegate is set here.
    request.delegate = self; 

    [s3Client putObject:request]; // This call doesn't block and immediately returns.

    ...
}

Since the request will be asynchronously dispatched and immediately returns, we need a mechanism to receive the actual response. The SDK does this through delegation. When you use delegates, your class needs to adapt the AmazonServiceRequestDelegate protocol.

#import <AWSiOSSDK/AmazonServiceRequest.h>

@interface YourViewController : UIViewController <AmazonServiceRequestDelegate>
{
...

As the client processes the request, it calls the appropriate delegate methods. Here are the two most common delegate methods. Please take a look at AmazonServiceRequest.h for all of the available delegate methods. They are all optional, so you can implement only the methods your app cares about.

#import "YourViewController.h"

@implementation YourViewController

...

- (void)request:(AmazonServiceRequest *)request didCompleteWithResponse:(AmazonServiceResponse *)response
{
    // The request successfully completed. Do something.
}

- (void)request:(AmazonServiceRequest *)request didFailWithServiceException:(NSException *)exception
{
    // The request failed with error. Do something.
}

...

Don’t make synchronous networking calls on the main thread

This is one of the most important guidelines when using the AWS SDK for iOS. Make sure you are not making synchronous calls on the main thread!

In iOS, the main thread is responsible for receiving UI events from the users and updating the UI. Depending on the network conditions of your app users and the size of the data they are handling, some AWS requests may take seconds, sometime minutes, to finish. If an app makes a synchronous call on the main thread and blocks it, the app will become sluggish and unacceptably unresponsive.

Watch out for the watchdog

To ensure the optimal user experience, iOS has a mechanism called watchdog to monitor bad behaving apps and kill them. If your app blocks the main thread and fails to respond to certain UI events in time, the watchdog kills your app.

On iTunes Connect, you can view the crash reports of your app. If you find an excessive number of "ate bad food" (0x8badf00d) exception codes, you may be doing synchronous networking in your app.

Exception Type: 00000020 Exception Codes: 0x8badf00d

Remember to always call AWS requests in an asynchronous manner!

Ways to make synchronous calls asynchronously

So, why do we offer synchronous operations in the AWS SDK for iOS when you should always make asynchronous calls to AWS? The synchronous operations are meant to be used with external asynchronous mechanisms such as Grand Central Dispatch and NSOperations. In the coming weeks, we will be posting additional blog posts on how to make synchronous calls asynchronously with these technologies.

As always, please leave a comment below if you have questions on this matter.

Further reading: