View PDF - AWS Documentation

View PDF - AWS Documentation
AWS Mobile SDK iOS Developer Guide
Release 0.0.3
Amazon Web Services
January 06, 2016
Contents
1
What Is the AWS SDK for iOS?
1.1 About the AWS Mobile Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2 About the SDK for iOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
Getting Started with the AWS Mobile SDK for iOS
2.1 Install AWS Mobile SDK for iOS . . . . . . . . . . . . .
2.2 Store and Retrieve Files with Amazon S3 . . . . . . . . .
2.3 Sync User Data with Amazon Cognito Sync . . . . . . .
2.4 Store and Query App Data in DynamoDB . . . . . . . . .
2.5 Tracking App Usage Data with Amazon Mobile Analytics
2.6 Writing App Data to Amazon Kinesis . . . . . . . . . . .
2.7 Building a Mobile Backend Using AWS Lambda . . . . .
2.8 Amazon Machine Learning . . . . . . . . . . . . . . . .
3
4
5
Set Up the SDK for iOS
3.1 Include the SDK for iOS in an Existing Application
3.2 Update the SDK to a Newer Version . . . . . . . . .
3.3 Preparing iOS 9 Apps . . . . . . . . . . . . . . . .
3.4 Getting Started with Swift . . . . . . . . . . . . . .
3.5 Getting Started with Objective-C . . . . . . . . . .
3.6 Logging . . . . . . . . . . . . . . . . . . . . . . . .
3.7 Sample Apps . . . . . . . . . . . . . . . . . . . . .
3.8 Install the Reference Documentation in Xcode . . .
Working with AWSTask
4.1 What is AWSTask? . . . . . . . . . . .
4.2 Working with Asynchronous Methods .
4.3 Handling Errors . . . . . . . . . . . .
4.4 Returning AWSTask or nil . . . . . . .
4.5 Executing Multiple Tasks . . . . . . .
4.6 Executing a Block on the Main Thread
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3
3
4
.
.
.
.
.
.
.
.
7
7
8
10
12
15
17
20
23
.
.
.
.
.
.
.
.
27
27
29
29
30
31
32
33
34
.
.
.
.
.
.
35
35
35
36
37
38
39
Preparing Your Apps for iOS 9
41
5.1 Determining if Your App is Affected . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
i
5.2
6
Resolving the Issue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Authenticate Users with Amazon Cognito Identity
6.1 Prerequisites . . . . . . . . . . . . . . . . . . . . . . .
6.2 Create an Identity Pool . . . . . . . . . . . . . . . . . .
6.3 Providing AWS Credentials . . . . . . . . . . . . . . .
6.4 Retrieving an Amazon Cognito ID and AWS Credentials
6.5 Integrating Identity Providers . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
45
45
45
46
46
47
7
Sync User Data with Amazon Cognito Sync
8
Track App Usage Data with Amazon Mobile Analytics
51
8.1 What is Amazon Mobile Analytics? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
8.2 Integrating Amazon Mobile Analytics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
9
Store and Retrieve Files with Amazon S3
9.1 Getting Started . . . . . . . . . . . . . . . . . . . . . . . . .
9.2 Download an Object . . . . . . . . . . . . . . . . . . . . . .
9.3 Upload an Object . . . . . . . . . . . . . . . . . . . . . . . .
9.4 Pause, Resume, and Cancel Object Transfers . . . . . . . . .
9.5 Track Progress . . . . . . . . . . . . . . . . . . . . . . . . .
9.6 Multipart Upload . . . . . . . . . . . . . . . . . . . . . . . .
9.7 Use Pre-Signed URLs to Transfer Objects in the Background
9.8 Use Server-Side Encryption . . . . . . . . . . . . . . . . . .
9.9 Additional Resources . . . . . . . . . . . . . . . . . . . . . .
10 Amazon S3 Transfer Utility for iOS (Beta)
10.1 Setting Up the S3 Transfer Utility . . .
10.2 Transferring Data . . . . . . . . . . . .
10.3 Managing Data Transfers . . . . . . .
10.4 Limitations . . . . . . . . . . . . . . .
49
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
55
55
57
59
60
61
61
61
63
64
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
65
65
66
71
71
11 Store and Retrieve App Data in Amazon DynamoDB
11.1 Getting Started . . . . . . . . . . . . . . . . . . .
11.2 Define a Mapping Class . . . . . . . . . . . . . .
11.3 Interact with Stored Objects . . . . . . . . . . . .
11.4 Perform a Scan . . . . . . . . . . . . . . . . . . .
11.5 Perform a Query . . . . . . . . . . . . . . . . . .
11.6 Conditional Writes Using the Low-Level Client . .
11.7 Batch Operations Using the Low-Level Client . .
11.8 Additional Resources . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
73
73
76
77
79
81
82
83
84
12 Process Streaming Data with Amazon Kinesis and Amazon Kinesis Firehose
12.1 What is Amazon Kinesis? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12.2 What is Amazon Kinesis Firehose? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12.3 Integrating Amazon Kinesis and Amazon Kinesis Firehose . . . . . . . . . . . . . . . . . .
85
85
86
86
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13 Execute Code On Demand with Amazon Lambda
89
13.1 Invoking a Amazon Lambda Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
ii
13.2 Client Context . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
13.3 Identity Context . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
14 Additional Resources
93
iii
iv
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
Welcome to the AWS Mobile SDK for iOS Developer Guide. This guide will help you start developing iOS
applications using Amazon Web Services.
If you’re new to the AWS Mobile SDK, you’ll probably want to look first at What Is the AWS SDK for
iOS? (page 3) and Getting Started with the AWS Mobile SDK for iOS (page 7). These topics explain what
the AWS Mobile SDK includes, how to set up the SDK, and how to get started using AWS services from an
iOS application.
After you’ve set up the SDK, you can start working with the mobile clients for Amazon Web Services. The
mobile clients are described in the service-specific topics. No matter which services you’re using, you
should provide AWS credentials to your app via Amazon Cognito. The Amazon Cognito credential
provider is discussed briefly in the various mobile service topics, and at length in Authenticate Users with
Amazon Cognito Identity (page 45).
Contents
1
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
2
Contents
CHAPTER 1
What Is the AWS SDK for iOS?
The AWS SDK for iOS is an open-source software development kit, distributed under an Apache Open
Source license. The SDK for iOS provides a library, code samples, and documentation to help developers
build connected mobile applications using AWS. This guide explains how to get started with the SDK for
iOS, how to work with related mobile services such as Amazon Cognito and Amazon Mobile Analytics,
and how to use Amazon Web Services effectively in a mobile app.
1.1 About the AWS Mobile Services
The AWS Mobile SDKs include client-side libraries for working with Amazon Web Services. These client
libraries provide high-level, mobile-optimized interfaces to services such as Amazon DynamoDB, Amazon
Simple Storage Service, and Amazon Kinesis.
The Mobile SDKs also include clients for Amazon Cognito; and Amazon Mobile Analytics—web services
designed specifically for use by mobile developers.
1.1.1 Amazon Cognito
Amazon Cognito facilitates the delivery of scoped, temporary credentials to mobile devices or other
untrusted environments, and it uniquely identifies a device or user and supplies the user with a consistent
identity throughout the lifetime of an application. The Amazon Cognito Sync service enables cross-device
syncing of application-related user data. Cognito also persists data locally, so that it’s available even if the
device is offline.
After you’ve set up the SDK, you can start using Amazon Cognito by following the instructions at
Authenticate Users with Amazon Cognito Identity (page 45) and Sync User Data with Amazon Cognito
Sync (page 49).
1.1.2 Amazon Mobile Analytics
Amazon Mobile Analytics lets you collect, visualize, and understand app usage for your mobile apps.
Reports are available for metrics on active users, sessions, retention, in-app revenue, and custom events,
and can be filtered by platform and date range.
3
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
After you’ve set up the SDK, you can start using Amazon Mobile Analytics by following the instructions at
Track App Usage Data with Amazon Mobile Analytics (page 51).
1.1.3 Amazon Simple Storage Service (S3)
Amazon Simple Storage Service (S3) provides secure, durable, highly-scalable object storage in the cloud.
Using the AWS Mobile SDK, you can directly access Amazon S3 from your mobile app.
After you’ve set up the SDK, you can start using Amazon S3 by following the instructions at Store and
Retrieve Files with Amazon S3 (page 55).
1.1.4 Amazon DynamoDB
Amazon DynamoDB is a fast, highly scalable, highly available, cost-effective, nonrelational database
service. DynamoDB removes traditional scalability limitations on data storage while maintaining low
latency and predictable performance.
After you’ve set up the SDK, you can start using Amazon DynamoDB by following the instructions at
Store and Retrieve App Data in Amazon DynamoDB (page 73).
1.1.5 Amazon Kinesis
Amazon Kinesis is a fully managed service for real-time processing of streaming data at massive scale.
After you’ve set up the SDK, you can start using Amazon Kinesis by following the instructions at Process
Streaming Data with Amazon Kinesis and Amazon Kinesis Firehose (page 85).
1.1.6 AWS Lambda
AWS Lambda is a compute service that runs your code in response to requests or events and automatically
manages the compute resources for you, making it easy to build applications that respond quickly to new
information.
After you’ve set up the SDK, you can start using AWS Lambda by following the instructions at Execute
Code On Demand with Amazon Lambda (page 89).
1.2 About the SDK for iOS
The AWS SDK for iOS includes:
• AWS iOS libraries – APIs that hide much of the lower-level plumbing of the web service interface,
including authentication, request retries, and error handling. Each service has its own library, so you
can include libraries for only the services you need.
• Code samples – Practical examples of using the libraries to build applications.
• Documentation – Reference documentation for the AWS SDK for iOS.
4
Chapter 1. What Is the AWS SDK for iOS?
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
The SDK is distributed as a .zip file containing the following:
• LICENSE
• NOTICE
• README.md
• frameworks/
– AWSCore.framework
– AWSAutoScaling.framework
– AWSCloudWatch.framework
– AWSDynamoDB.framework
– AWSEC2.framework
– AWSElasticLoadBalancing.framework
– AWSKinesis.framework
– AWSLambda.framework
– AWSMachineLearning.framework
– AWSMobileAnalytics.framework
– AWSS3.framework
– AWSSES.framework
– AWSSimpleDB.framework
– AWSSNS.framework
– AWSSQS.framework
• extras/
– AWSCognito.framework - The framework for Amazon Cognito sync.
– Amazon Software License.txt
– NOTICE
• documentation/ – Contains documentation, including a docset, for the AWS SDK for iOS.
• samples/ – Contains an HTML document that links to samples, which are named based on the
services that they demonstrate.
• src/ – Contains an HTML document that links to source, which contains the implementation and
header files for the AWS iOS libraries.
1.2. About the SDK for iOS
5
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
6
Chapter 1. What Is the AWS SDK for iOS?
CHAPTER 2
Getting Started with the AWS Mobile SDK for iOS
The AWS SDK for iOS provides the libraries, samples and, documentation needed to call AWS services
from iOS apps. This guide will walk you through the following:
2.1 Install AWS Mobile SDK for iOS
The AWS Mobile SDK is installed using CocoaPods. If you don’t have CocoaPods installed, see Install
CocoaPods (http://cocoapods.org).
Create a new project in Xcode, and in your project’s directory, create file called podfile. Add the following
text to the podfile you just created:
source 'https://github.com/CocoaPods/Specs.git'
pod 'AWSCore'
pod 'AWSAutoScaling'
pod 'AWSCloudWatch'
pod 'AWSDynamoDB'
pod 'AWSEC2'
pod 'AWSElasticLoadBalancing'
pod 'AWSKinesis'
pod 'AWSLambda'
pod 'AWSMachineLearning'
pod 'AWSMobileAnalytics'
pod 'AWSS3'
pod 'AWSSES'
pod 'AWSSimpleDB'
pod 'AWSSNS'
pod 'AWSSQS'
pod 'AWSCognito'
In a terminal window, navigate to your project directory and run the following command:
pod install
This will install the AWS Mobile SDK and any needed dependencies. Next, reopen your project using the
newly generated .xcworkspace file
Your project now has the AWS Mobile SDK for iOS installed.
7
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
For more detailed infomration about installing the AWS Mobile SDK for iOS, see Set Up the SDK for iOS
(page 27)
2.2 Store and Retrieve Files with Amazon S3
2.2.1 Authenticate Users with Cognito Identity
Cognito Identity provides secure access to AWS services. Identities are managed by an identity pool. Roles
specify resources an identity can access and are associated with an identity pool. To create an identity pool
for your application:
1. Log into the Cognito Console (https://console.aws.amazon.com/cognito/home) and click the New
Identity Pool button
2. Give your Identity Pool a unique name and enable access to unauthenticated identities
3. Click the Create Pool button and then the Update Roles to create your identity pool and associated
roles
For more information on Cognito Identity, see Authenticate Users with Amazon Cognito Identity (page 45)
Add the following import statement:
#import <AWSCore/AWSCore.h>
Add the following code to application:didFinishLaunchingWithOptions method:
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc]
identityPoolId:@"<your-identity-pool-arn>"];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AW
credentialsProvider:credentialsProvider];
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
Note: If you have an existing credential provider, you do not need to create a new one.
For more information on Cognito Identity, see Authenticate Users with Amazon Cognito Identity (page 45).
2.2.2 Grant Access to your S3 Resources
Configure your Cognito Identity to have access to the S3 buckets in your AWS account:
1. Navigate to the Identity and Access Management Console
(https://console.aws.amazon.com/iam/home) and click Roles in the left-hand pane.
2. Type your Identity Pool name into the search box - two roles will be listed one for unauthenticated
users and one for authenticated users.
3. Click the role for unauthenticated users (it will have unauth appended to your Identity Pool name).
8
Chapter 2. Getting Started with the AWS Mobile SDK for iOS
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
4. Click the Create Role Policy button, select Policy Generator, and click the Select button.
5. In the Edit Permissions page make the settings shown in the following image:
Note: These settings will give your Identity Pool full access to all of the S3 buckets in your AWS account.
6. Click the Add Statement button and then the Next Step button.
7. The Wizard will show you the configuration generated, click the Apply Policy button.
For more information on granting access to S3, see Granting Access to an Amazon S3 Bucket
(http://blogs.aws.amazon.com/security/post/Tx3VRSWZ6B3SHAV/Writing-IAM-Policies-How-to-grantaccess-to-an-Amazon-S3-bucket).
2.2.3 Upload a File to Amazon S3
Create a AWSS3TransferManagerUploadRequest instance specifying the file to upload and the destination
bucket:
AWSS3TransferManagerUploadRequest *uploadRequest = [AWSS3TransferManagerUploadRequest new];
uploadRequest.bucket = @"example-bucket";
uploadRequest.key = @"test.txt";
uploadRequest.body = self.downloadFileURL;
Submit the upload request to the S3 service asynchronously:
AWSS3TransferManager *transferManager = [AWSS3TransferManager defaultS3TransferManager];
[[transferManager upload:uploadRequest] continueWithExecutor:[AWSExecutor mainThreadExecuto
withBlock:^id(AWSTask *task) {
if (task.error != nil) {
NSLog(@"%s %@","Error uploading :", uploadRequest.key);
}
else { NSLog(@"Upload completed"); }
return nil;
}];
2.2. Store and Retrieve Files with Amazon S3
9
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
2.2.4 Download a File from Amazon S3
Create a destination URL where file will be downloaded:
NSString *downloadingFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:File
NSURL *downloadingFileURL = [NSURL fileURLWithPath:downloadingFilePath];
Create the download request:
AWSS3TransferManagerDownloadRequest *downloadRequest = [AWSS3TransferManagerDownloadRequest
downloadRequest.bucket = BucketName;
downloadRequest.key = FileName;
downloadRequest.downloadingFileURL = downloadingFileURL;
Submit the download request:
AWSS3TransferManager *transferManager = [AWSS3TransferManager defaultS3TransferManager];
self.txtLabel.text = @"Download started, please wait...";
[[transferManager download:downloadRequest] continueWithExecutor:[AWSExecutor mainThreadExe
withBlock:^id(AWSTask *task){
if (task.error != nil) {
NSLog(@"%s %@","Error downloading :", downloadRequest.key);
}
else {
NSLog(@"download completed");
self.txtLabel.text = @"Download completed";
}
return nil;
}];
This exercise assumes the use of an unauthenticated identity provided by Amazon Cognito. For more
information on using authenticated identities, see Authenticate Users with Amazon Cognito Identity
(page 45).
For more information on accessing Amazon S3 from an iOS application, see Calling Amazon S3 from iOS
Apps (http://docs.aws.amazon.com/mobile/sdkforios/developerguide/s3transfermanager.html).
2.3 Sync User Data with Amazon Cognito Sync
2.3.1 Authenticate Users with Amazon Cognito Identity
Amazon Cognito Identity provides secure access to AWS services. Identities are managed by an identity
pool. Roles specify resources an identity can access and are associated with an identity pool. To create an
identity pool for your application:
1. Log into the Cognito Console (https://console.aws.amazon.com/cognito) and click the New Identity
Pool button
2. Give your Identity Pool a unique name and enable access to unauthenticated identities
10
Chapter 2. Getting Started with the AWS Mobile SDK for iOS
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
3. Click the Create Pool button and then the Update Roles to create your identity pool and associated
roles
For more information on Cognito Identity, see Authenticate Users with Amazon Cognito Identity (page 45)
Note: The auto-generated Roles include the permissions needed to access Cognito Sync, so no further
configuration is required.
The next page displays code that creates a credential provider that provides a Cognito Identity for your app
to use. Copy the code from Steps 1 & 2 into your AppDelegate.m file as shown below:
Add the following import statements:
#import <AWSCore/AWSCore.h>
#import <AWSCognito/AWSCognito.h>
Add the following code to application:didFinishLaunchingWithOptions method:
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc]
identityPoolId:@"<your-identity-pool-arn>"];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AW
credentialsProvider:credentialsProvider];
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
Note: If you have an existing credential provider, you do not need to create a new one.
For more information on Cognito Identity, see Authenticate Users with Amazon Cognito Identity (page 45)
2.3.2 Syncing User Data
To sync unauthenticated user data:
1. Create a dataset and add user data.
2. Synchronize the dataset with the cloud.
2.3.3 Create a Dataset and Add User Data
Create an instance of AWSCognitoDataset. User data is added in the form of key/value pairs. Dataset
objects are created with the AWSCognito class which functions as a Cognito client object. Use the
defaultCognito method to get a reference to the default singleton instance of AWSCognito. The
openOrCreateDataset method is used to create a new dataset or open an existing instance of a dataset stored
locally on the device:
AWSCognitoDataset *dataset = [[AWSCognito defaultCognito] openOrCreateDataset:datasetName];
User data is added to an AWSCognitoDataset instance using the setString:forKey or setValue:forKey
methods. The following code snippet shows how to add some user data to a dataset:
2.3. Sync User Data with Amazon Cognito Sync
11
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
[dataset setString:@"John Doe" forKey:@"Username"];
[dataset setString:@"10000" forKey:@"HighScore"];
2.3.4 Synchronize Dataset with the Cloud
To sync the dataset with the cloud, call the synchronize method on the dataset object:
[dataset synchronize];
All data written to datasets will be stored locally until the dataset is synced. The code in this section
assumes you are using an unauthenticated Cognito identity, so when the user data is synced with the cloud
it will be stored per device. The device has a device ID associated with it, when the user data is synced to
the cloud, it will be associated with that device ID.
To sync user data across devices (based on an authenticated Cognito Identity) see Sync User Data with
Amazon Cognito Sync (page 49).
2.3.5 Related Documentation
Authenticate Users with Amazon Cognito Identity (page 45)
Developer Authenticated Identities (http://docs.aws.amazon.com/mobile/sdkforios/developerguide/cognitoauth.html#using-developer-authenticated-identities)
2.4 Store and Query App Data in DynamoDB
2.4.1 Authenticate Users with Cognito Identity
Cognito Identity provides secure access to AWS services. Identities are managed by an identity pool. Roles
specify resources an identity can access and are associated with an identity pool. To create an identity pool
for your application:
1. Log into the Cognito Console (https://console.aws.amazon.com/cognito/home) and click the New
Identity Pool button
2. Give your Identity Pool a unique name and enable access to unauthenticated identities
3. Click the Create Pool button and then the Update Roles to create your identity pool and associated
roles
For more information on Cognito Identity, see Authenticate Users with Amazon Cognito Identity (page 45)
The next page displays code that creates a credential provider that provides a Cognito Identity for your app
to use. Copy the code from Steps 1 & 2 into your AppDelegate.m file as shown below:
Add the following import statement:
#import <AWSDynamoDB/AWSDynamoDB.h>
12
Chapter 2. Getting Started with the AWS Mobile SDK for iOS
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
Add the following code to application:didFinishLaunchingWithOptions method:
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc]
identityPoolId:CognitoIdentityPoolId];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:De
credentialsProvider:credentialsProvider];
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
Note: If you have an existing credential provider, you do not need to create a new one.
Click Go to Dashboard to return to the Cognito Console.
2.4.2 Update IAM Roles
In order for your Cognito Identities to access Amazon DynamoDB, you must modify the Roles associated
with your Identity Pool.
1. Navigate to the Identity and Access Management Console
(https://console.aws.amazon.com/iam/home) and click Roles in the left-hand pane and search for
your Identity Pool name - two roles will be listed one for unauthenticated users and one for
authenticated users
2. Click the role for unauthenticated users (it will have “unauth” appended to your Identity Pool name)
and click the Attach Role Policy button
3. Select Policy Generator and click the Select button
4. In the Edit Permissions page enter the settings shown in the following image:
The Amazon Resource Name (ARN) of a DynamoDB table is composed of the region in which the table is
located, and the owners’ AWS account number. For example:
"arn:aws:dynamodb:us-west-2:123456789012:table/table-name".
For more information about specifying ARNs, see Amazon Resource Names for DynamoDB
(http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/UsingIAMWithDDB.html#ARN_Format).
2.4. Store and Query App Data in DynamoDB
13
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
5. Click the Add Statement button, click the Next Step button and the Wizard will show you the
configuration generated
6. Click the Apply Policy button
2.4.3 Write a Row
To write a row to the table, define a class to hold your row data. This class must be derived from
AWSDynamoDBModel and implement the AWSDynamoDBModel interface. The class should also
contain properties that hold the attribute data for the row. The following class declaration illustrates such a
class:
@interface Book : AWSDynamoDBObjectModel <AWSDynamoDBModeling>
@property
@property
@property
@property
(nonatomic,
(nonatomic,
(nonatomic,
(nonatomic,
strong)
strong)
strong)
strong)
NSString
NSString
NSNumber
NSString
*Title;
*Author;
*Price;
*ISBN;
@end
The following code illustrates the implementation of the class:
@implementation Book
+ (NSString *)dynamoDBTableName {
return @"Books";
}
+ (NSString *)hashKeyAttribute {
return @"ISBN";
}
@end
To insert a row, instantiate the class and set its properties:
Book *myBook = [Book new];
myBook.ISBN = @"3456789012";
myBook.Title = @"The Scarlet Letter";
myBook.Author = @"Nathaniel Hawthorne";
myBook.Price = [NSNumber numberWithInt:899];
And pass the object to the AWSDyanmoDBObjectMapper’s save method:
[[dynamoDBObjectMapper save:myBook]
continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"The request failed. Error: [%@]", task.error);
}
if (task.exception) {
NSLog(@"The request failed. Exception: [%@]", task.exception);
}
14
Chapter 2. Getting Started with the AWS Mobile SDK for iOS
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
if (task.result) {
//Do something with the result.
}
return nil;
}];
To update a row, modify the instance of the DDTableRow class and call AWSDynamoObjectMapper.save
as shown above.
2.4.4 Retrieve a Row
To retrieve a row, instantiate the object to hold the retrieved data and set its primary key and call the
AWSDynamoDBObjectMapper class’ load method. The following code illustrates calling the load method:
[[dynamoDBObjectMapper load:[Book class] hashKey:@"6543210987" rangeKey:nil]
continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"The request failed. Error: [%@]", task.error);
}
if (task.exception) {
NSLog(@"The request failed. Exception: [%@]", task.exception);
}
if (task.result) {
Book *book = task.result;
//Do something with the result.
}
return nil;
}];
For more information on accessing DynamoDB from an iOS application, see Calling Amazon DynamoDB
in an iOS App (http://docs.aws.amazon.com/mobile/sdkforios/developerguide/dynamodb_om.html)
2.5 Tracking App Usage Data with Amazon Mobile Analytics
Add the following import statement:
#import <AWSMobileAnalytics/AWSMobileAnalytics.h>
2.5.1 Integrating Amazon Mobile Analytics
The sections below explain how to integrate Mobile Analytics with your app.
Create an App in the Mobile Analytics Console
Go to the Amazon Mobile Analytics console (https://console.aws.amazon.com/mobileanalytics/home) and
create an app. Note the appId value, as you’ll need it later.
2.5. Tracking App Usage Data with Amazon Mobile Analytics
15
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
Note: To learn more about working in the console, see the Amazon Mobile Analytics User Guide
(http://docs.aws.amazon.com/mobileanalytics/latest/ug/).
Integrate the SDK into Your App
If you haven’t already done so, download the SDK for iOS (http://aws.amazon.com/mobile/sdk/), unzip it,
and include it in your application as described at Set Up the SDK for iOS (page 27). The instructions direct
you to import the headers for the services you’ll be using. For this example, you need one of the following
imports:
#import <AWSCore/AWSCore.h>
Initialize the Mobile Analytics Client
Initialize an instance of the AWSMobileAnalytics class. In doing so, you’ll need to provide the
appId value that you generated in the Mobile Analytics console. The appId is used to group your data in
the Mobile Analytics console.
AWSMobileAnalytics *analytics = [AWSMobileAnalytics mobileAnalyticsForAppId:@"yourAppId" id
where “yourAppId” is the appId value from the Amazon Mobile Analytics console and “cognitoId” is the
Cognito identity pool ID.
Add Monetization Events
The SDK for iOS provides the AWSMobileAnalyticsAppleMonetizationEventBuilder
class, which helps you build monetization events to track purchases from Apple’s IAP Framework.
To learn more about adding
monetization events, see the API reference guide for AWSMobileAnalyticsAppleMonetizationEventBuilder
(http://docs.aws.amazon.com/AWSiOSSDK/latest/Classes/AWSMobileAnalyticsAppleMonetizationEventBuilder.html).
Record Custom Events
To record custom events, we first need to get the event client from the AWSMobileAnalytics instance.
id<AWSMobileAnalyticsEventClient> eventClient = analytics.eventClient;
For this example, let’s say your app is a game, and you want to record an event when a user completes a
level. Create a “LevelComplete” event.
id<AWSMobileAnalyticsEvent> levelEvent = [eventClient createEventWithEventType:@"LevelCompl
Note that custom events can’t start with an underscore (_), or they’ll be filtered out.
Add attributes and metrics to the event in key-value pairs.
16
Chapter 2. Getting Started with the AWS Mobile SDK for iOS
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
[levelEvent addAttribute:@"Upper Dungeon" forKey:@"LevelName"];
[levelEvent addAttribute:@"Moderately difficult" forKey:@"Difficulty"];
[levelEvent addMetric:@1763 forKey:@"TimeToComplete"];
Record the event.
[eventClient recordEvent:levelEvent];
Events are submitted automatically when the user goes into the background. However, if you want to
submit events manually, you can do so with the submitEvents method:
[eventClient submitEvents];
If you don’t call submitEvents, events will automatically be submitted at periodic intervals.
2.6 Writing App Data to Amazon Kinesis
Amazon Kinesis (http://aws.amazon.com/kinesis/) is a fully managed service for real-time processing of
streaming data at massive scale.
2.6.1 Authenticate Users with Cognito Identity
Cognito Identity provides secure access to AWS services. Identities are managed by an identity pool. Roles
specify resources an identity can access and are associated with an identity pool. To create an identity pool
for your application:
1. Log into the Cognito Console (https://console.aws.amazon.com/cognito/home) and click the New
Identity Pool button.
2. Give your Identity Pool a unique name and enable access to unauthenticated identities.
3. Click the Create Pool button and then the Update Roles to create your identity pool and associated
roles.
Add the following import statement:
#import <AWSCore/AWSCore.h>
Add the following code to application:didFinishLaunchingWithOptions method:
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc]
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AW
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
Note: If you have an existing credential provider, you do not need to create a new one.
For more information on Cognito Identity, see Authenticate Users with Amazon Cognito Identity (page 45)
2.6. Writing App Data to Amazon Kinesis
17
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
2.6.2 Grant Role Access to Your Kinesis Stream
To use Kinesis in an application, you must allow the IAM roles associated with your Cognito Identity Pool
access to your Kinesis stream. To set this policy:
1. Navigate to the Identity and Access Management Console
(https://console.aws.amazon.com/iam/home) and choose Roles in the left-hand pane.
2. Type your Identity Pool name into the search box. Two roles will be listed: one for unauthenticated
users and one for authenticated users.
3. Choose the role for unauthenticated users (it will have “unauth” appended to your Identity Pool
name).
4. Scroll down the web page until you see the Create Role Policy. Choose it, select Policy Generator,
and then choose the Select button.
5. Select the Allow radio button, Amazon Kinesis in the AWS Service drop-down, PutRecord under
Actions, and enter the ARN to your Kinesis stream in the Amazon Resource Name (ARN) text box.
6. Choose the Add Statement button, the Next Step button, and the Apply Policy button.
To learn more about Kinesis-specific policies, see Controlling Access to Amazon Kinesis Resources with
IAM (http://docs.aws.amazon.com/kinesis/latest/dev/kinesis-using-iam.html).
2.6.3 Grant Role Access to Your Kinesis Firehose Delivery Stream
To use Kinesis Firehose in an application, you must allow the IAM roles associated with your Amazon
Cognito Identity Pool access to your Kinesis Firehose delivery stream. To set this policy:
1. Navigate to the Identity and Access Management Console
(https://console.aws.amazon.com/iam/home) and choose Roles in the left-hand pane.
2. Type your Identity Pool name into the search box. Two roles will be listed: one for unauthenticated
users and one for authenticated users.
3. Choose the role for unauthenticated users (it will have “unauth” appended to your Identity Pool
name).
4. Scroll down the web page until you see the Create Role Policy. Choose it, select Policy Generator,
and then choose the Select button.
5. Select the Allow radio button, Amazon Kinesis in the AWS Service drop-down, PutRecord under
Actions, and enter the ARN to your Kinesis Firehose delivery stream in the Amazon Resource Name
(ARN) text box.
6. Choose the Add Statement button, the Next Step button, and the Apply Policy button.
To learn more about Kinesis Firehose-specific policies, see Controlling Access to Amazon Kinesis
Firehose (http://docs.aws.amazon.com/firehose/latest/dev/controlling-access.html).
18
Chapter 2. Getting Started with the AWS Mobile SDK for iOS
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
2.6.4 Configure the Kinesis Service Client
Add the following import statement:
#import <AWSKinesis/AWSKinesis.h>
Use the AWSKinesisRecorder to interact with the Kinesis service. The following snippet returns a
shared instance of the Kinesis service client:
AWSKinesisRecorder *kinesisRecorder = [AWSKinesisRecorder defaultKinesisRecorder];
Configure the AWSKinesisRecorder through its properties:
kinesisRecorder.diskAgeLimit = 30 * 24 * 60 * 60; // 30 days
kinesisRecorder.diskByteLimit = 10 * 1024 * 1024; // 10MB
kinesisRecorder.notificationByteThreshold = 5 * 1024 * 1024; // 5MB
2.6.5 Save Records to Local Storage
With AWSKinesisRecorder created and configured, you can use saveRecord:streamName: to
save records to local storage:
// Create some text data
NSData *yourData = [@"Test_data" dataUsingEncoding:NSUTF8StringEncoding];
// save the data to local storage
[kinesisRecorder saveRecord:yourData streamName:@"YourStreamName"]
2.6.6 Submit Records to an Amazon Kinesis Stream
Use the submitAllRecords asynchronous method on the AWSKinesisRecorder object to send all
locally saved records to your Kinesis stream. Both saveRecord and submitAllRecords are
asynchronous operations, so you should ensure that saveRecord is complete before you invoke
submitAllRecords. The following code sample shows the how to call these methods using the
AWSTask:
// Create an task array to track the saveRecord calls.
NSMutableArray *tasks = [NSMutableArray new];
// Call saveRecord for each record
for (int32_t i = 0; i < 100; i++) {
[tasks addObject:[kinesisRecorder saveRecord:[[NSString stringWithFormat:@"TestStri
}
// When all of the saveRecord calls have completed, call submitAllRecords to write all reco
// to the Kinesis stream
[[[AWSTask taskForCompletionOfAllTasks:tasks] continueWithSuccessBlock:^id(AWSTask *task) {
return [kinesisRecorder submitAllRecords];
}] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"Error: [%@]", task.error);
2.6. Writing App Data to Amazon Kinesis
19
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
}
return nil;
}];
To learn more about working with Amazon Kinesis, see the Amazon Kinesis Developer Resources
(http://aws.amazon.com/kinesis/developer-resources/). To learn more about working with Amazon Kinesis
Firehose, see the Amazon Kinesis Firehose Documentation
(http://aws.amazon.com/documentation/firehose/). To learn more about the Kinesis classes, see the class
reference for AWSKinesisRecorder
(http://docs.aws.amazon.com/AWSiOSSDK/latest/Classes/AWSKinesisRecorder.html).
2.7 Building a Mobile Backend Using AWS Lambda
Amazon Lambda is a compute service that runs your code in response to events and automatically manages
the compute resources for you, making it easy to build applications that respond quickly to new
information. The Mobile SDK for iOS enables you to call Lambda functions from your iOS mobile apps.
2.7.1 Create an Amazon Lambda function
To create a Amazon Lambda function, see Amazon Lambda Getting Started
(http://docs.aws.amazon.com/lambda/latest/dg/getting-started-custom-events.html)
2.7.2 Authenticate Users with Cognito Identity
Amazon Cognito Identity provides secure access to AWS services. Identities are managed by an identity
pool. Roles specify resources an identity can access and are associated with an identity pool. To create an
identity pool for your application:
1. Log into the Amazon Cognito Console (https://console.aws.amazon.com/cognito/home) and click
the New Identity Pool button
2. Give your Identity Pool a unique name and enable access to unauthenticated identities
3. Click the Create Pool button and then the Update Roles to create your identity pool and associated
roles
For more information on Amazon Cognito Identity, see Authenticate Users with Amazon Cognito Identity
(page 45)
2.7.3 Set Permissions
To use Amazon Lambda in an application, you must set the correct permissions. The following IAM policy
allows the user to perform the actions shown in this tutorial on an given Amazon Lambda function
identified by ARN:
20
Chapter 2. Getting Started with the AWS Mobile SDK for iOS
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
{
"Statement": [{
"Effect": "Allow",
"Action": [
"lambda:invokefunction"
],
"Resource": [
"resource-id",
]
}]
}
Replace the “resource-id” in the sample above with the ARN of your AWS Lambda function. Apply this
policy to the unauthenticated role assigned to your Cognito identity pool, replacing the resource-id value
with the correct ARN for your Lambda function.
1. Log in to the IAM console: Amazon IAM console
2. Select Roles and select the “Unauth” role that Cognito created for you.
3. Click Attach Role Policy.
4. Select Custom Policy and click Select.
5. Enter a name for your policy and paste in the policy document shown above, replacing the Resource
values with the ARNs for your function. You can view the ARN for your function in the Amazon
Lambda console.
6. Click Apply Policy.
To learn more about IAM policies, see Using IAM
(http://docs.aws.amazon.com/IAM/latest/UserGuide/IAM_Introduction.html).
Add the following import statements:
#import <AWSCore/AWSCore.h>
Add the following code to application/:didFinishLaunchingWithOptions method/:
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc]
identityPoolId:@"<your-identity-pool-arn>"];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AW
credentialsProvider:credentialsProvider];
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
Note: If you have an existing credential provider, you do not need to create a new one.
You must replace <your-identity-pool-arn> with the ARN of your Amazon Cognito Identity Pool. For more
information on Amazon Cognito Identity, see Authenticate Users with Amazon Cognito Identity (page 45)
2.7. Building a Mobile Backend Using AWS Lambda
21
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
2.7.4 Integrate the SDK into Your App
If you haven’t already done so, download the SDK for iOS (http://aws.amazon.com/mobile/sdk/), unzip it,
and include it in your application as described at Set Up the SDK for iOS (page 27). The instructions direct
you to import the headers for the services you’ll be using. For this example, you need the following import:
#import <AWSLambda/AWSLambda.h>
2.7.5 Invoke a Amazon Lambda Function with AWSLambdaInvoker
Get a reference to the defualt instance of AWSLambdaInvoker:
AWSLambdaInvoker *lambdaInvoker = [AWSLambdaInvoker defaultLambdaInvoker];
You can pass parameters to your Amazon Lambda Function using a dictionary, an array, or a string. The
following snippets illuststrate each of these options.
// Invoke with dictionary input
AWSLambdaInvoker *lambdaInvoker = [AWSLambdaInvoker defaultLambdaInvoker]
NSDictionary *parameters = @{@"key1" : @"value1",
@"key2" : @"value2",
@"key3" : @"value3",
@"isError" : @NO};
[[lambdaInvoker invokeFunction:LambdaFunctionName
JSONObject:parameters] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"Error: %@", task.error);
}
if (task.exception) {
NSLog(@"Exception: %@", task.exception);
}
if (task.result) {
NSLog(@"Result: %@", task.result);
dispatch_async(dispatch_get_main_queue(), ^{
[self printOutputJSON:task.result];
});
}
return nil;
}];
// Invoke with array input
AWSLambdaInvoker *lambdaInvoker = [AWSLambdaInvoker defaultLambdaInvoker];
NSArray *parameters = @[@"John", @"Smith"];
[[lambdaInvoker invokeFunction:LambdaFunctionName
JSONObject:parameters] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"Error: %@", task.error);
}
if (task.exception) {
NSLog(@"Exception: %@", task.exception);
22
Chapter 2. Getting Started with the AWS Mobile SDK for iOS
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
}
if (task.result) {
NSLog(@"Result: %@", task.result);
dispatch_async(dispatch_get_main_queue(), ^{
[self printOutputJSON:task.result];
});
}
return nil;
}];
// Invoke with string input
AWSLambdaInvoker *lambdaInvoker = [AWSLambdaInvoker defaultLambdaInvoker];
NSString *parameters = @"Hello";
[[lambdaInvoker invokeFunction:LambdaFunctionName
JSONObject:parameters] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"Error: %@", task.error);
}
if (task.exception) {
NSLog(@"Exception: %@", task.exception);
}
if (task.result) {
NSLog(@"Result: %@", task.result);
dispatch_async(dispatch_get_main_queue(), ^{
[self printOutputJSON:task.result];
});
}
return nil;
}];
For more information on accessing AWS Lambda, see Execute Code On Demand with Amazon Lambda
(page 89).
2.8 Amazon Machine Learning
Amazon Machine Learning (ML) is a service that makes it easy for developers of all skill levels to use
machine learning technology. The SDK for iOS provides a simple, high-level client designed to help you
interface with Amazon Machine Learning service. The client enables you to call Amazon ML’s real-time
API to retrieve predictions from your models and enables you to build mobile applications that request and
take actions on predictions. The client also enables you to retrieve the real-time prediction endpoint URLs
for your ML models.
2.8.1 Integrate Amazon Machine Learning
To use the Amazon Machine Learning mobile client, you’ll need to integrate the SDK for iOS into your
app and import the necessary libraries. To do so, follow these steps:
2.8. Amazon Machine Learning
23
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
1. Download the SDK and unzip it as described in Setup the SDK for iOS
(http://docs.aws.amazon.com/mobile/sdkforios/developerguide/setup.html)
2. The instructions direct you to import the headers for the services you’ll be using. For Amazon
Machine Learning, you need the following import:
#import <AWSMachineLearning/AWSMachineLearning.h>
Configure Credentials
You can use Amazon Cognito to provide temporary AWS credentials to your application. These credentials
let the app access your AWS resources. To create a credentials provider, follow the instructions at
Providing AWS Credentials
(http://docs.aws.amazon.com/mobile/sdkforios/developerguide/cognito-auth.html#providing-creds-iOS).
To use Amazon Machine Learning in an application, you must set the proper permissions. The following
IAM policy allows the user to perform the actions shown in this tutorial on two actions identified by ARN:
{
"Statement": [{
"Effect": "Allow",
"Action": [
"machinelearning:GetMLModel",
"machinelearning:Predict"
],
"Resource": "arn:aws:machinelearning:use-east-1:11122233444:mlmodel/example-model-id"
}]
}
This policy should be applied to roles assigned to the Amazon Cognito identity pool, but you will need to
replace the Resource value with the correct account ID and ML Model ID. You can apply policies at the
IAM console (https://console.aws.amazon.com/iam/home). To learn more about IAM policies, see
Introduction to IAM (http://docs.aws.amazon.com/IAM/latest/UserGuide/IAM_Introduction.html).
Create an Amazon Machine Learning Client
Once you’ve imported the necessary libraries and have your credentials object, you can instantiate
AWSMachineLearningGetMLModelInput.
AWSMachineLearningGetMLModelInput *getMLModelInput = [AWSMachineLearningGetMLModelInput new
Making a Predict Request
Prior to calling Predict, make sure you have not only a completed ML Model ID but also a created
real-time endpoint for that ML Model ID. This cannot be done through the mobile SDK; you will have to
use the Machine Learning Console (https://console.aws.amazon.com/machinelearning) or an alternate SDK
(http://docs.aws.amazon.com/AWSSdkDocsJava/latest/DeveloperGuide/welcome.html). To validate that
this ML can be used for real-time Predictions:
24
Chapter 2. Getting Started with the AWS Mobile SDK for iOS
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
// Use a created model that has a created real-time endpoint
NSString *MLModelId = @"example-model-id";
// Call GetMLModel to get the realtime endpoint URL
AWSMachineLearningGetMLModelInput *getMLModelInput = [AWSMachineLearningGetMLModelInput new
getMLModelInput.MLModelId = MLModelId;
[[[MachineLearning getMLModel:getMLModelInput] continueWithSuccessBlock:^id(AWSTask *task)
AWSMachineLearningGetMLModelOutput *getMLModelOutput = task.result;
// Validate that the ML model is completed
if (getMLModelOutput.status != AWSMachineLearningEntityStatusCompleted) {
NSLog(@"ML Model is not completed");
return nil;
}
// Validate that the realtime endpoint is ready
if (getMLModelOutput.endpointInfo.endpointStatus != AWSMachineLearningRealtimeEndpointS
NSLog(@"Realtime endpoint is not ready");
return nil;
}
}
Once the real-time endpoint is ready, we can begin calling Predict. Note that you must pass the real-time
endpoint through the PredictRequest.
// Create a Predict request with your ML Model id and the appropriate Record mapping.
AWSMachineLearningPredictInput *predictInput = [AWSMachineLearningPredictInput new];
predictInput.predictEndpoint = getMLModelOutput.endpointInfo.endpointUrl;
predictInput.MLModelId = MLModelId;
predictInput.record = @{};
// Call and return prediction
return [MachineLearning predict:predictInput];
Additional Resources
• Developer Guide (http://docs.aws.amazon.com/machine-learning/latest/dg)
• API Reference (http://docs.aws.amazon.com/machine-learning/latest/APIReference)
For more information about the AWS SDK for iOS see AWS Mobile SDK for iOS (page 1) For more
information about other AWS SDKs see AWS Mobile SDK (http://aws.amazon.com/mobile/sdk/)
2.8. Amazon Machine Learning
25
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
26
Chapter 2. Getting Started with the AWS Mobile SDK for iOS
CHAPTER 3
Set Up the SDK for iOS
To get started with the AWS SDK for iOS, you can set up the SDK and start building a new project, or you
integrate the SDK in an existing project. You can also run the samples to get a sense of how the SDK
works.
To use the AWS SDK for iOS, you will need the following installed on your development machine:
• Xcode 7 or later
• iOS 7 or later
At the AWS GitHub repo, you can check out the SDK source code (https://github.com/aws/aws-sdk-ios).
3.1 Include the SDK for iOS in an Existing Application
The samples included with the SDK for iOS are standalone projects that are already set up for you. You
can also integrate the SDK for iOS with your own existing project. There are two ways to import the AWS
Mobile SDK for iOS into your project:
• CocoaPods
• Frameworks
You should use one of these two ways to import the AWS Mobile SDK but not both. Importing both ways
loads two copies of the SDK into the project and causes compiler errors.
3.1.1 CocoaPods
1. The AWS Mobile SDK for iOS is available through CocoaPods (http://cocoapods.org/). If you have
not installed CocoaPods, install it by running the command:
$ sudo gem install cocoapods
2. In your project directory (the directory where your *.xcodeproj file is), create a plain text file
named Podfile (without any file extension) and add the lines below. If you want to use Amazon
Cognito Sync, make sure to include pod “AWSCognitoSync” as well:
27
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
source 'https://github.com/CocoaPods/Specs.git'
pod 'AWSCore'
pod 'AWSAutoScaling'
pod 'AWSCloudWatch'
pod 'AWSDynamoDB'
pod 'AWSEC2'
pod 'AWSElasticLoadBalancing'
pod 'AWSKinesis'
pod 'AWSLambda'
pod 'AWSMachineLearning'
pod 'AWSMobileAnalytics'
pod 'AWSS3'
pod 'AWSSES'
pod 'AWSSimpleDB'
pod 'AWSSNS'
pod 'AWSSQS'
pod 'AWSCognito'
3. Then run the following command:
$ pod install
4. Open up *.xcworkspace with Xcode and start using the SDK.
Note: Do NOT use *.xcodeproj. If you open up a project file instead of a workspace, you receive an
error.
3.1.2 Frameworks
1. Download the SDK from http://aws.amazon.com/mobile/sdk. The SDK is stored in a compressed file
archive named aws-ios-sdk-#.#.# (where ‘#.#.#’ represents the version number, so for version
2.2.2, the filename is aws-ios-sdk-2.2.2).
Note: The size of AWSiOSSDKv2.framework is > 65MB; however, it does not add > 65MB to your
app binary when imported to your project. To learn more about the size of the app binary, see the
note under “Frameworks” (https://github.com/aws/aws-sdk-ios/#frameworks).
2. With your project open in Xcode, Control+click Frameworks and then click Add files to “<project
name>”....
3. In Finder, navigate to the AWSxxx.framework (where ‘xxx’ is the AWS service you wish to use)
file, select the following files, and click Add.
• AWSCore.framework
• AWSAutoScaling.framework
• AWSCloudWatch.framework
• AWSDynamoDB.framework
• AWSEC2.framework
28
Chapter 3. Set Up the SDK for iOS
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
• AWSElasticLoadBalancing.framework
• AWSKinesis.framework
• AWSLambda.framework
• AWSMachineLearning.framework
• AWSMobileAnalytics.framework
• AWSS3.framework
• AWSSES.framework
• AWSSimpleDB.framework
• AWSSNS.framework
• AWSSQS.framework
• extras/AWSCognito.framework (for Cognito Sync)
4. Open a target for your project, select Build Phases, expand Link Binary With Libraries, click the
+ button, and add libsqlite3.dylib and libz.dylib and
SystemConfiguration.framework.
3.2 Update the SDK to a Newer Version
When a new version of the SDK is released, you can pick up the changes as described below.
3.2.1 CocoaPods
Run the following command in your project directory. CocoaPods automatically picks up the new changes.
$ pod update
Note: If your pod is having an issue, you can delete Podfile.lock and Pods/ and then run pod
install to cleanly install the SDK.
3.2.2 Frameworks
Follow the installation process shown previously to include the new version of the SDK.
3.3 Preparing iOS 9 Apps
The release of iOS 9 includes changes that might impact how your apps interact with some AWS services.
If you compile your apps with Apple’s iOS 9 SDK (or Xcode 7), there are additional steps you must
complete for your app to successfully connect with any AWS service you need to call. For more
3.2. Update the SDK to a Newer Version
29
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
information, see Preparing Your Apps for iOS 9
(http://docs.aws.amazon.com/mobile/sdkforios/developerguide/ats.html).
3.4 Getting Started with Swift
1. Create an Objective-C bridging header file using Xcode.
2. In the bridging header, import the appropriate headers for the services you are using. The header file
import convention for CocoaPods is #import "SERVICENAME.h", and for frameworks it is
#import <FRAMEWORKNAME/SERVICENAME.h>, as in the following examples:
#import
#import
#import
#import
#import
#import
<AWSCore/AWSCore.h>
<AWSS3/AWSS3.h>
<AWSDynamoDB/AWSDynamoDB.h>
<AWSSQS/AWSSQS.h>
<AWSSNS/AWSSNS.h>
<AWSCognito/AWSCognito.h>
3. From Your Target > Build Settings > Objective-C Bridging Header, point Objective-C Bridging
Header to the bridging header you just created.
4. Import the AWSCore header in the application delegate:
#import <AWSCore/AWSCore.h>
5. Create a default service configuration by adding the following code snippet in the
application:didFinishLaunchingWithOptions: application delegate method:
let credentialsProvider = AWSCognitoCredentialsProvider(
regionType: AWSRegionType.USEast1, identityPoolId: cognitoIdentityPoolId)
let defaultServiceConfiguration = AWSServiceConfiguration(
region: AWSRegionType.USEast1, credentialsProvider: credentialsProvider)
AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = defaultService
6. Make a call to the AWS services:
let dynamoDB = AWSDynamoDB.defaultDynamoDB()
let listTableInput = AWSDynamoDBListTablesInput()
dynamoDB.listTables(listTableInput).continueWithBlock{ (task: AWSTask!) -> AnyObject!
if let error = task.error {
print("Error occurred: \(error)")
return nil
}
let listTablesOutput = task.result as AWSDynamoDBListTablesOutput
for tableName : AnyObject in listTablesOutput.tableNames {
print("\(tableName)")
}
30
Chapter 3. Set Up the SDK for iOS
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
return nil
}
Note: Most of the service client classes have a singleton method to get a default client. The naming
convention is + defaultSERVICENAME (e.g. + defaultDynamoDB in the above code
snippet). This singleton method creates a service client with
defaultServiceConfiguration, which you set up in step 5, and maintains a strong
reference to the client.
3.5 Getting Started with Objective-C
1. Import the AWSCore header in the application delegate:
#import <AWSCore/AWSCore.h>
2. Create a default service configuration by adding the following code snippet in the
application:didFinishLaunchingWithOptions: application delegate method.:
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider a
identityPoolId:CognitoPoolID];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegi
credentialsProvider:credentialsProvider];
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
3. Import service headers where you want to use the services. The header file import convention for
frameworks is #import <FRAMEWORKNAME/SERVICENAME.h>, as in the following examples:
#import
#import
#import
#import
#import
#import
<AWSCore/AWSCore.h>
<AWSS3/AWSS3.h>
<AWSDynamoDB/AWSDynamoDB.h>
<AWSSQS/AWSSQS.h>
<AWSSNS/AWSSNS.h>
<AWSCognito/AWSCognito.h>
4. Make a call to the AWS services:
AWSS3Transfermanager *transferManager = [AWSS3Transfermanager defaultS3TransferManager
AWSS3TransferManagerUploadRequest *uploadRequest = [AWSS3TransferManagerUploadRequest
uploadRequest.bucket = yourBucket;
uploadRequest.key = yourKey;
uploadRequest.body = yourDataURL;
uploadRequest.contentLength = [NSNumber numberWithUnsignedLongLong:fileSize];
[[transferManager upload:uploadRequest] continueWithBlock:^id(AWSTask *task) {
// Do something with the response
return nil;
}];
3.5. Getting Started with Objective-C
31
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
Note: Most of the service client classes have a singleton method to get a default client. The naming
convention is + defaultSERVICENAME (e.g. + defaultS3TransferManager in the
above code snippet). This singleton method creates a service client with
defaultServiceConfiguration, which you set up in step 5, and maintains a strong
reference to the client.
3.6 Logging
Changing log levels during development may make debugging easier. You can change the log level by
importing AWSCore.h and calling:
Swift:
AWSLogger.defaultLogger().logLevel = .Verbose
The following logging level options are available:
• .None
• .Error (This is the default. Only error logs are printed to the console.)
• .Warn
• .Info
• .Debug
• .Verbose
Objective-C:
[AWSLogger defaultLogger].logLevel = AWSLogLevelVerbose;
The following logging level options are available:
• AWSLogLevelNone
• AWSLogLevelError (This is the default. Only error logs are printed to the console.)
• AWSLogLevelWarn
• AWSLogLevelInfo
• AWSLogLevelDebug
• AWSLogLevelVerbose
3.6.1 Get AWS Credentials with Amazon Cognito or AWS Identity and Access Management
We recommend using Amazon Cognito as your credential provider to access AWS services from your
mobile app. Cognito provides a secure mechanism to access AWS services without having to embed
32
Chapter 3. Set Up the SDK for iOS
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
credentials in your app. To learn more, see Authenticate Users with Amazon Cognito Identity (page 45).
Alternatively, you can use AWS Identity and Access Management (http://aws.amazon.com/iam/) (IAM). If
you choose IAM, ensure that your role’s policy is minimally scoped so that it can only perform the desired
actions for the service being used.
3.7 Sample Apps
The AWS SDK for iOS includes sample apps that demonstrate common use cases.
Cognito Sync Sample (Objective-C
(https://github.com/awslabs/aws-sdk-ios-samples/tree/master/CognitoSync-Sample/Objective-C/))
This sample demonstrates how to securely manage and sync your mobile app data and create unique
identities via login providers including Facebook, Google, and Login with Amazon.
AWS Services Demonstrated:
• Amazon Cognito Sync (http://aws.amazon.com/cognito/)
• Amazon Cognito Identity (http://aws.amazon.com/cognito/)
DynamoDB Object Mapper Sample (Swift <https://github.com/awslabs/aws-sdk-iossamples/tree/master/DynamoDBObjectMapper-Sample/Swift>‘__‘Objective-C
(https://github.com/awslabs/aws-sdk-ios-samples/tree/master/DynamoDBObjectMapperSample/Objective-C/))
This sample demonstrates how to insert / update / delete / query items using DynamoDB Object Mapper.
AWS Services Demonstrated:
• Amazon DynamoDB (http://aws.amazon.com/cognito/)
• Amazon Cognito Identity (http://aws.amazon.com/cognito/)
S3 Transfer Manager Sample (Swift
(https://github.com/awslabs/aws-sdk-ios-samples/tree/master/S3TransferManager-Sample/Swift/),
Objective-C
(https://github.com/awslabs/aws-sdk-ios-samples/tree/master/S3TransferManager-Sample/Objective-C/))
This sample demonstrates how to upload / download multiple files simultaneously using S3 Transfer
Manager. It also shows how to pause, resume, and cancel file upload / download.
AWS Services Demonstrated:
• Amazon S3 (http://aws.amazon.com/s3/)
• Amazon Cognito Identity (http://aws.amazon.com/cognito/)
SNS Mobile Push and Mobile Analytics Sample (Swift
(https://github.com/awslabs/aws-sdk-ios-samples/tree/master/SNS-MobileAnalytics-Sample/Swift/),
Objective-C (https://github.com/awslabs/aws-sdk-ios-samples/tree/master/SNS-MobileAnalyticsSample/Objective-C/))
3.7. Sample Apps
33
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
This sample demonstrates how to set up Amazon SNS Mobile Push and record events using Amazon
Mobile Analytics.
AWS Services Demonstrated:
• Amazon SNS Mobile Push (http://aws.amazon.com/sns/)
• Amazon Mobile Analytics (http://aws.amazon.com/mobileanalytics/)
• Amazon Cognito Identity (http://aws.amazon.com/cognito/)
3.8 Install the Reference Documentation in Xcode
The AWS SDK for iOS includes documentation in the DocSets format that you can view within Xcode.
The easiest way to install the documentation is to use the Mac OS X terminal.
3.8.1 To install the DocSet for Xcode
Open the Mac OS X terminal and go to the directory containing the expanded archive. For example:
$ cd ~/Downloads/aws-ios-sdk-2.2.2
Note: Remember to replace 2.2.2 in the example above with the actual version number of the AWS
SDK for iOS that you downloaded.
Create a directory called ~/Library/Developer/Shared/Documentation/DocSets:
$ mkdir -p ~/Library/Developer/Shared/Documentation/DocSets
Copy (or move) documentation/com.amazon.aws.ios.docset from the SDK installation files
to the directory you created in the previous step:
$ mv documentation/com.amazon.aws.ios.docset ~/Library/Developer/Shared/Documentation/DocSe
If Xcode was running during this procedure, restart Xcode. To browse the documentation, go to Help, click
Documentation and API Reference, and select AWS SDK for iOS v2.0 Documentation (where ‘2.0’ is
the appropriate version number).
34
Chapter 3. Set Up the SDK for iOS
CHAPTER 4
Working with AWSTask
To use the SDK for iOS effectively, you’ll need to work with AWSTask objects. AWSTask is a class that
makes it easier to work with asynchronous operations without blocking the UI thread.
The AWSTask class is a renamed version of BFTask from the Bolts framework. For complete
documentation on Bolts, see the Bolts-iOS repo (https://github.com/BoltsFramework/Bolts-iOS).
4.1 What is AWSTask?
An AWSTask object represents the result of an asynchronous method. Using AWSTask, you can wait for
an asynchronous method to return a value, and then do something with that value after it has returned. You
can chain async requests instead of nesting them. This helps keep logic clean and code readable.
4.2 Working with Asynchronous Methods
When you’re working with the AWS Mobile SDK for iOS, it’s import to remember that methods that return
AWSTask are asynchronous. For example, AWSKinesisRecorder defines the following methods:
- (AWSTask *)saveRecord:(NSData *)data
streamName:(NSString *)streamName;
- (AWSTask *)submitAllRecords;
These methods are asynchronous and return immediately. This means that the following code snippet may
not submit testData to the Amazon Kinesis stream:
AWSKinesisRecorder *kinesisRecorder = [AWSKinesisRecorder defaultKinesisRecorder];
NSData *testData = [@"test-data" dataUsingEncoding:NSUTF8StringEncoding];
[kinesisRecorder saveRecord:testData
streamName:@"test-stream-name"];
[kinesisRecorder submitAllRecords];
The problem is that saveRecord:streamName: may return before it persists the record on the disk, in
which case submitAllRecords won’t see the saved record on disk.
35
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
Here’s the correct way to submit the data:
AWSKinesisRecorder *kinesisRecorder = [AWSKinesisRecorder defaultKinesisRecorder];
NSData *testData = [@"test-data" dataUsingEncoding:NSUTF8StringEncoding];
[[[kinesisRecorder saveRecord:testData
streamName:@"test-stream-name"] continueWithSuccessBlock:^id(AWSTask *ta
return [kinesisRecorder submitAllRecords];
}] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"Error: %@", task.error);
}
return nil;
}];
Note that the submitAllRecords call is made within the continueWithSuccessBlock:
because we want to execute submitAllRecords after saveRecord:streamName: successfully
finishes executing. The continueWithBlock: and continueWithSuccessBlock: won’t
execute until the previous asynchronous call has already finished executing. Thus, in the example above,
submitAllRecords is guaranteed to see the result of saveRecord:streamName:.
4.3 Handling Errors
The continueWithBlock: and continueWithSuccessBlock: work in similar ways; both
ensure that the previous asynchronous method has finished executing before the subsequent block is
executed. However, they have one important difference: continueWithSuccessBlock: will be
skipped if an error occurred in the previous operation, but continueWithBlock: is always executed.
For example, consider the following scenarios, which refer to the code snippet above:
saveRecord:streamName: succeeded and submitAllRecords succeeded. In this scenario,
program flow will proceed as follows:
1. saveRecord:streamName: is successfully executed.
2. continueWithSuccessBlock: is executed.
3. submitAllRecords is successfully executed.
4. continueWithBlock: is executed.
5. Because task.error is nil, it doesn’t log an error.
6. Done.
saveRecord:streamName: succeeded and submitAllRecords failed. In this scenario, program
flow will proceed as follows:
1. saveRecord:streamName: is successfully executed.
2. continueWithSuccessBlock: is executed.
3. submitAllRecords is executed with an error.
4. continueWithBlock: is executed.
36
Chapter 4. Working with AWSTask
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
5. Because task.error is NOT nil, it logs an error from submitAllRecords.
6. Done.
saveRecord:streamName: failed. In this scenario, program flow will proceed as follows:
1. saveRecord:streamName: is executed with an error.
2. continueWithSuccessBlock: is skipped and will NOT be executed.
3. continueWithBlock: is executed.
4. Because task.error is NOT nil, it logs an error from saveRecord:streamName:.
5. Done.
Note that the code doesn’t check for task.error in continueWithSuccessBlock:, and
NSLog(@"Error: %@", task.error); may print out an error from either
submitAllRecords or saveRecord:streamName:. This is a way to consolidate error handling
logic at the end of the execution chain.
If you want each block to deal with its own errors, you can rewrite the code snippet as follows:
AWSKinesisRecorder *kinesisRecorder = [AWSKinesisRecorder defaultKinesisRecorder];
NSData *testData = [@"test-data" dataUsingEncoding:NSUTF8StringEncoding];
[[[kinesisRecorder saveRecord:testData
streamName:@"test-stream-name"] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"Error from 'saveRecord:streamName:': %@", task.error);
return nil;
}
return [kinesisRecorder submitAllRecords];
}] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"Error from 'submitAllRecords': %@", task.error);
}
return nil;
}];
In this snippet, NSLog(@"Error from ’saveRecord:streamName:’: %@",
task.error); only logs an error from saveRecord:streamName:, and NSLog(@"Error
from ’submitAllRecords’: %@", task.error); logs an error from
submitAllRecords. By using continueWithBlock: and continueWithSuccessBlock:
properly, you can flexibly control the error handling flow.
4.4 Returning AWSTask or nil
In the above code snippet, we return nil at the end of continueWithBlock:, indicating successful
execution of the block. We are required to return either AWSTask or nil in every
continueWithBlock: and continueWithSuccessBlock:. In most cases, Xcode warns you
when you forget to return one of these values, but it won’t catch all such omissions. If you forget to return
AWSTask or nil and Xcode doesn’t catch the error, an app crash may result.
4.4. Returning AWSTask or nil
37
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
Make sure you always return AWSTask or nil.
4.5 Executing Multiple Tasks
If you want to execute a large number of operations, you have two options: executing in sequence or
executing in parallel.
4.5.1 In Sequence
Let’s say you want to submit 100 records to a Kinesis stream in sequence. You can do so as follows:
AWSKinesisRecorder *kinesisRecorder = [AWSKinesisRecorder defaultKinesisRecorder];
AWSTask *task = [AWSTask taskWithResult:nil];
for (int32_t i = 0; i < 100; i++) {
task = [task continueWithSuccessBlock:^id(AWSTask *task) {
NSData *testData = [[NSString stringWithFormat:@"TestString-%02d", i] dataUsingEnco
return [kinesisRecorder saveRecord:testData
streamName:@"test-stream-name"];
}];
}
[task continueWithSuccessBlock:^id(AWSTask *task) {
return [kinesisRecorder submitAllRecords];
}];
In this case, the key is to concatenate a series of tasks by reassigning task:
task = [task continueWithSuccessBlock:^id(AWSTask *task) {
4.5.2 In Parallel
You can execute multiple methods in parallel by using taskForCompletionOfAllTasks: as
follows:
AWSKinesisRecorder *kinesisRecorder = [AWSKinesisRecorder defaultKinesisRecorder];
NSMutableArray *tasks = [NSMutableArray new];
for (int32_t i = 0; i < 100; i++) {
NSData *testData = [[NSString stringWithFormat:@"TestString-%02d", i] dataUsingEncoding
[tasks addObject:[kinesisRecorder saveRecord:testData
streamName:@"test-stream-name"]];
}
[[AWSTask taskForCompletionOfAllTasks:tasks] continueWithSuccessBlock:^id(AWSTask *task) {
return [kinesisRecorder submitAllRecords];
}];
38
Chapter 4. Working with AWSTask
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
Here we create an instance of NSMutableArray, put all of our tasks in it, and then pass it to
taskForCompletionOfAllTasks:, which is successful only when all of the tasks are successfully
executed. This approach may be faster, but it may consume more system resources. Also, some AWS
services, such as Amazon DynamoDB, throttle a large number of certain requests. Choose a sequential or
parallel approach based on your use case.
4.6 Executing a Block on the Main Thread
By default, continueWithBlock: and continueWithSuccessBlock: are executed on a
background thread. But in some cases (for example, updating a UI component based on the result of a
service call), you need to execute an operation on the main thread. To execute an operation on the main
thread, you can use Grand Central Dispatch or AWSExecutor.
4.6.1 Grand Central Dispatch
You can use dispatch_async(dispatch_get_main_queue(), ^{...}); to execute a block
on the main thread. In the following example, we create a UIAlertView on the main thread when record
submission fails:
AWSKinesisRecorder *kinesisRecorder = [AWSKinesisRecorder defaultKinesisRecorder];
NSData *testData = [@"test-data" dataUsingEncoding:NSUTF8StringEncoding];
[[[kinesisRecorder saveRecord:testData
streamName:@"test-stream-name"] continueWithSuccessBlock:^id(AWSTask *ta
return [kinesisRecorder submitAllRecords];
}] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alertView =
[[UIAlertView alloc] initWithTitle:@"Error!"
message:[NSString stringWithFormat:@"Error: %@",
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alertView show];
});
}
return nil;
}];
4.6.2 AWSExecutor
Another option is to use AWSExecutor:
AWSKinesisRecorder *kinesisRecorder = [AWSKinesisRecorder defaultKinesisRecorder];
NSData *testData = [@"test-data" dataUsingEncoding:NSUTF8StringEncoding];
[[[kinesisRecorder saveRecord:testData
4.6. Executing a Block on the Main Thread
39
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
streamName:@"test-stream-name"] continueWithSuccessBlock:^id(AWSTask *ta
return [kinesisRecorder submitAllRecords];
}] continueWithExecutor:[AWSExecutor mainThreadExecutor] withBlock:^id(AWSTask *task) {
if (task.error) {
UIAlertView *alertView =
[[UIAlertView alloc] initWithTitle:@"Error!"
message:[NSString stringWithFormat:@"Error: %@", tas
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alertView show];
}
return nil;
}];
In this case, withBlock: is executed on the main thread.
40
Chapter 4. Working with AWSTask
CHAPTER 5
Preparing Your Apps for iOS 9
The release of iOS 9 includes changes that might impact how your apps interact with some AWS services.
If you compile your apps with Apple’s iOS 9 SDK (or Xcode 7), Apple’s App Transport Security (ATS)
(https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/) feature
may affect the ability of apps to connect to certain AWS service endpoints. In order to ensure affected apps
continue to successfully connect to AWS endpoints, you’ll need to configure them to interact properly with
Apple’s ATS by adding these properties to your Info.plist file:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>amazonaws.com</key>
<dict>
<key>NSThirdPartyExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
<key>amazonaws.com.cn</key>
<dict>
<key>NSThirdPartyExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
If you are not planning to recompile your apps with Apple’s iOS 9 SDK (or Xcode 7) to run on iOS 9
devices, you do not need to make any configuration changes.
41
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
5.1 Determining if Your App is Affected
If your app stops working after upgrading to Xcode 7 and iOS 9, follow these steps to determine if it
affected by ATS.
1. Turn on verbose logging of the AWS Mobile SDK for iOS by calling the following line in the application:didFinishLaunchingWithOptions: application delegate.
Swift:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [NSObject : AnyObject]?) -> Bool {
...
AWSLogger.defaultLogger().logLevel = .Verbose
...
return true
}
}
Objective-C:
#import <AWSCore/AWSCore.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
[AWSLogger defaultLogger].logLevel = AWSLogLevelVerbose;
...
return YES;
}
@end
2. Run your app and make a request to an AWS service.
3. Search your log output for “SSL”. If you find the “An SSL error has occurred and a secure
connection to the server cannot be made” message, your app is affected by the ATS changes:
2015-10-06 11:39:13.402 DynamoDBSampleSwift[14467:303540] CFNetwork SSLHandshake faile
2015-10-06 11:39:13.403 DynamoDBSampleSwift[14467:303540] NSURLSession/NSURLConnection
2015-10-06 11:39:13.569 DynamoDBSampleSwift[14467:303540] CFNetwork SSLHandshake faile
2015-10-06 11:39:13.569 DynamoDBSampleSwift[14467:303540] NSURLSession/NSURLConnection
Error: Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secur
If you cannot find the SSL handshake error message, it is possible that another problem caused your
app to stop working. Some internal behaviors change with major operating system updates, and it is
42
Chapter 5. Preparing Your Apps for iOS 9
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
common for previously unseen issues to surface. You can post the versions of Xcode, iOS, and the
AWS Mobile SDK, code snippets, and steps to reproduce the issue on our forum
(https://forums.aws.amazon.com/forum.jspa?forumID=88) or GitHub
(https://github.com/aws/aws-sdk-ios/issues) so that we can assist you in identifying the issue.
5.2 Resolving the Issue
If you see the SSL handshake error, follow these steps to resolve the issue.
1. Locate your Info.plist and from the context menu select Open As > Source Code.
2. Copy and paste the ATS exception to be a direct child of the top level <dict> tag.
5.2. Resolving the Issue
43
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
After following these steps, your app should be able to access AWS endpoints while running on iOS 9.
44
Chapter 5. Preparing Your Apps for iOS 9
CHAPTER 6
Authenticate Users with Amazon Cognito Identity
Using Amazon Cognito, you can create unique identities for your users and authenticate them for secure
access to your AWS resources. Amazon Cognito supports public identity providers—Amazon, Facebook,
Twitter, and Google—as well as unauthenticated identities. Amazon Cognito also supports developer
authenticated identities, which let you register and authenticate users via your own backend authentication
process, while still using Amazon Cognito to synchronize user data and access AWS resources. For
information about Amazon Cognito Identity Region availability, see AWS Service Region Availability
(http://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/).
To use AWS services in your app, you must include AWSxxx.framework (where ‘xxx’ is the AWS
service you wish to use) in your project.
6.1 Prerequisites
To integrate Amazon Cognito with your app, you need the following:
• An AWS account
(https://portal.aws.amazon.com/gp/aws/developer/registration/index.html?nc2=h_ct)
• An Xcode development environment (https://developer.apple.com/xcode/)
• AWS Mobile SDK for iOS (http://aws.amazon.com/mobile/sdk/)
• Optionally, a developer account and an application registered with the identity provider you want to
use (Facebook (https://developers.facebook.com/), Google (https://developers.google.com/), Twitter
(https://dev.twitter.com/), or Amazon (http://login.amazon.com/))
6.2 Create an Identity Pool
To use Amazon Cognito in your app, you’ll need to create an identity pool. An identity pool is a store of
user identity data specific to your account. Using Sync User Data with Amazon Cognito Sync (page 49),
you can retrieve the data across client platforms, devices, and operating systems, so that if a user starts
using your app on a phone and later switches to a tablet, the persisted app information is still available for
that user. To create a new identity pool, log in to the Amazon Cognito console
45
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
(https://console.aws.amazon.com/cognito/). The New Identity Pool wizard will guide you through the
configuration process.
6.3 Providing AWS Credentials
You can use Amazon Cognito to deliver temporary, limited-privilege credentials to your application, so that
your users can access AWS resources. Amazon Cognito supports both authenticated and unauthenticated
users.
To provide AWS credentials to your app, follow the steps below.
1. In the Amazon Cognito console (https://console.aws.amazon.com/cognito/), create an identity pool
and download or copy the starter code snippets.
2. If you haven’t already done so, add the AWSCore.framework to your project. (For more
information, see Set Up the SDK for iOS (page 27)).
3. In your source code, include the AWSCore header:
#import <AWSCore/AWSCore.h>
4. Initialize the Amazon Cognito credentials provider using the code snippet generated by the Amazon
Cognito Console. The value for COGNITO_IDENTITY_POOL will be specific to your account:
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider a
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegi
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
Note: If you created your identity pool before February 2015, you will need to reassociate your roles with
your identity pool in order to use this constructor. To do so, open the Cognito Console
(https://console.aws.amazon.com/cognito), select your identity pool, click Edit Identity Pool, specify your
authenticated and unauthenticated roles, and save the changes.
6.4 Retrieving an Amazon Cognito ID and AWS Credentials
Once the login tokens are set in the credentials provider, you can retrieve a unique Amazon Cognito
identifier for your end user and temporary credentials that let the app access your AWS resources:
// Retrieve your Amazon Cognito ID.
NSString *cognitoId = credentialsProvider.identityId;
The unique identifier is available in the identityId property of the credentials provider object.
Once the Amazon Cognito credentials provider is initialized, you can use it to create clients for other
Amazon Web Services. The example below shows how to create an Amazon DynamoDB client:
46
Chapter 6. Authenticate Users with Amazon Cognito Identity
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
// get a client with the default service configuration
AWSDynamoDB *dynamoDB = [AWSDynamoDB defaultDynamoDB];
The credentials provider communicates with Amazon Cognito, retrieving a unique identifier for the user as
well as temporary, limited privilege AWS credentials for the AWS Mobile SDK. The retrieved credentials
are valid for one hour.
6.5 Integrating Identity Providers
With Amazon Cognito, you can create unique end user identifiers for accessing AWS cloud services by
using public login providers such as Amazon, Facebook, Google, Twitter and any OpenID Connect
compatible provider, or by using your own user identity system. With these identifiers you can store app
data in the Amazon Cognito sync store or access other AWS services like Amazon S3 or Amazon
DynamoDB. For information on how to use “External Identity Providers” with Amazon Cognito, please
see the Amazon Cognito Developer Guide
(http://docs.aws.amazon.com/cognito/devguide/identity/external-providers/).
6.5. Integrating Identity Providers
47
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
48
Chapter 6. Authenticate Users with Amazon Cognito Identity
CHAPTER 7
Sync User Data with Amazon Cognito Sync
Amazon Cognito Sync is an AWS service and client library that enables cross-device syncing of
application-related user data. You can use the Amazon Cognito Sync API to synchronize user profile data
across devices and across login providers—Amazon, Facebook, Google, and your own custom identity
provider. To use Amazon Cognito Sync in your app, you must include AWSCognitoSync.framework
in your project.
For information about Cognito Sync, see Amazon Cognito Sync Developer Guide
(http://docs.aws.amazon.com/cognito/devguide/sync/).
49
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
50
Chapter 7. Sync User Data with Amazon Cognito Sync
CHAPTER 8
Track App Usage Data with Amazon Mobile Analytics
Using Amazon Mobile Analytics, you can track customer behaviors, aggregate metrics, generate data
visualizations, and identify meaningful patterns. The AWS SDK for iOS provides integration with the
Amazon Mobile Analytics service. For information about AWS service region availability or Mobile
Analytics region availability, see AWS Service Region Availability
(http://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/).
8.1 What is Amazon Mobile Analytics?
Amazon Mobile Analytics lets you collect, visualize, and understand app usage for your iOS, Android,
FireOS, Windows Phone, Blackberry mobile apps as well as desktop and web apps running on Windows,
OS X, and Linux. Reports are available for metrics on active users, sessions, retention, in-app revenue, and
custom events, and can be filtered by platform and date range. Amazon Mobile Analytics is built to scale
with your business and can collect and process billions of events from many millions of endpoints.
To learn more about Mobile Analytics, see the Amazon Mobile Analytics User Guide
(http://docs.aws.amazon.com/mobileanalytics/latest/ug/)
8.1.1 IAM Policy for Amazon Mobile Analytics
To use Amazon Mobile Analytics, AWS users must have the correct permissions. The following IAM
policy allows the user to submit events to Amazon Mobile Analytics:
{
"Statement": [{
"Effect": "Allow",
"Action": "mobileanalytics:PutEvents",
"Resource": "*"
}]
}
This policy should be assigned to roles associated with the Cognito identity pool for your app. The policy
allows clients to record events with the Mobile Analytics service. Amazon Cognito will set this policy for
you, if you let it create new roles. Other policies are required to allow IAM users to view reports.
51
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
You can set permissions at https://console.aws.amazon.com/iam/. To learn more about IAM policies, see
Using IAM (http://docs.aws.amazon.com/IAM/latest/UserGuide/IAM_Introduction.html).
8.2 Integrating Amazon Mobile Analytics
The sections below explain how to integrate Amazon Mobile Analytics with your app.
8.2.1 Create an App in the Amazon Mobile Analytics Console
Go to the Amazon Mobile Analytics console (https://console.aws.amazon.com/mobileanalytics/home) and
create an app. Note the appId value, as you’ll need it later.
To learn more about creating new apps in the console, see Managing Apps
(http://docs.aws.amazon.com/mobileanalytics/latest/ug/managing-apps.html) in the Amazon Mobile
Analytics User Guide.
8.2.2 Integrate the SDK into Your App
If you haven’t already done so, download the SDK for iOS (http://aws.amazon.com/mobile/sdk/), unzip it,
and include it in your application as described at Set Up the SDK for iOS (page 27). The instructions direct
you to import the headers for the services you’ll be using:
#import <AWSMobileAnalytics/AWSMobileAnalytics.h>
Initialize an AWSMobileAnalytics client. In doing so, you’ll need to provide the appId value that
you generated in the Amazon Mobile Analytics console. The appId is used to group your data in the
Amazon Mobile Analytics console.
AWSMobileAnalytics *analytics = [AWSMobileAnalytics mobileAnalyticsForAppId:@"yourAppId" id
where “yourAppId” is the appId value from the Amazon Mobile Analytics console and “cognitoId” is the
Cognito identity pool ID.
8.2.3 Add Monetization Events
The SDK for iOS provides the AWSMobileAnalyticsAppleMonetizationEventBuilder
class, which helps you build monetization events to track purchases from Apple’s IAP Framework.
To learn more about monetization events, see:
• AWSMobileAnalyticsAppleMonetizationEventBuilder
(http://docs.aws.amazon.com/AWSiOSSDK/latest/Classes/AWSMobileAnalyticsAppleMonetizationEventBuilder.htm
in the API Reference Guide.
• Creating Monetization Events
(http://docs.aws.amazon.com/mobileanalytics/latest/ug/defining-a-monetization-event-sdk.html) in
the Amazon Mobile Analytics User Guide.
52
Chapter 8. Track App Usage Data with Amazon Mobile Analytics
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
8.2.4 Record Custom Events
To record custom events, we first need to get the event client from the AWSMobileAnalytics instance.
id<AWSMobileAnalyticsEventClient> eventClient = analytics.eventClient;
For this example, let’s say your app is a game, and you want to record an event when a user completes a
level. Create a “LevelComplete” event.
id<AWSMobileAnalyticsEvent> levelEvent = [eventClient createEventWithEventType:@"LevelCompl
Note that custom events can’t start with an underscore (_), or they’ll be filtered out.
Add attributes and metrics to the event in key-value pairs.
[levelEvent addAttribute:@"Upper Dungeon" forKey:@"LevelName"];
[levelEvent addAttribute:@"Moderately difficult" forKey:@"Difficulty"];
[levelEvent addMetric:@1763 forKey:@"TimeToComplete"];
Record the event.
[eventClient recordEvent:levelEvent];
Events are submitted automatically when the user goes into the background. However, if you want to
submit events manually, you can do so with the submitEvents method:
[eventClient submitEvents];
If you don’t call submitEvents, events will automatically be submitted at periodic intervals.
To learn more about custom events, see:
• AWSMobileAnalyticsEventClient
(http://docs.aws.amazon.com/AWSiOSSDK/latest/Classes/AWSMobileAnalytics.html#//api/name/eventClient)
in the API Reference Guide.
• AWSMobileAnalyticsEvent
(http://docs.aws.amazon.com/AWSiOSSDK/latest/Protocols/AWSMobileAnalyticsEvent.html) in
the API Reference Guide.
• Creating a Custom Event
(http://docs.aws.amazon.com/mobileanalytics/latest/ug/creating-a-custom-event-sdk.html) in the
Amazon Mobile Analytics User Guide.
8.2. Integrating Amazon Mobile Analytics
53
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
54
Chapter 8. Track App Usage Data with Amazon Mobile Analytics
CHAPTER 9
Store and Retrieve Files with Amazon S3
Amazon Simple Storage Service (S3) (http://aws.amazon.com/s3/) provides secure, durable,
highly-scalable object storage in the cloud. Using the AWS Mobile SDK, you can directly access Amazon
S3 from your mobile app.
Amazon S3 Transfer Manager makes it easy for you to upload and download files from S3 while
optimizing for performance and reliability. It hides the complexity of transferring files behind a simple
API. Whenever possible, uploads are broken up into multiple pieces, so that several pieces can be sent in
parallel to provide better throughput. This approach enables more robust transfers, since an I/O error in any
individual piece means the SDK only needs to retransmit the one affected piece, and not the entire transfer.
S3 Transfer Manager provides simple APIs to pause, resume, and cancel file transfers. or information
about S3 Region availability, see AWS Service Region Availability
(http://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/).
9.1 Getting Started
This section provides a step-by-step guide for getting started with Amazon S3 using the AWS Mobile SDK
for iOS. You can also try out the Aazon S3 sample
(https://github.com/awslabs/aws-sdk-ios-samples/tree/master/S3TransferManager-Sample/Objective-C)
available in the AWSLabs GitHub repository.
9.1.1 Get the SDK
To use S3 with your mobile app, first set up the AWS Mobile SDK for iOS:
1. Download the iOS SDK and include it in your iOS project, as described at Set Up the SDK for iOS
(page 27).
2. Import the following header into your project:
#iport <AWSS3/AWSS3.h>
55
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
9.1.2 Conigure Credentials
Amazon Cognito lets you create unique end user identifiers for accessing AWS cloud services. You’ll use
Cognito to provide temporary AWS credentials to your app.
Log in to the Cognito console (https://console.aws.amazon.com/cognito/).
Create an identity pool and copy the Cognito client initialization code into your project. For more
information on setting up the Cognito client, see Cognito Identity Developer Guide
(http://docs.aws.amazon.com/cognito/devguide/identity/).
9.1.3 Create and Configure an S3 Bucket
Amazon S3 stores your resources in buckets—cloud storage containers that live in a specific region
(http://docs.aws.amazon.com/general/latest/gr/rande.html). Each S3 bucket must ave a globally unique
name.
Let’s use the AWS Management Console to create an S3 bucket.
Create an S3 Bucket
1. Sign in to the S3 console (https://console.aws.amazon.com/s3/) and click Create Bucket.
2. Enter a bucket name, select a region, and click create.
Grant Access to Your S3 Resources
The default IAM role policy grants your application access to Amazon Mobile Analytics and Amazon
Cognito Sync. In order for your Cognito identity pool to access Amazon S3, you must modify the identity
pool’s roles.
1. Navigate to the Identity and Access Management Console
(https://console.aws.amazon.com/iam/home) and click Roles in the left-hand pane.
2. Type your identity pool name into the search box. Two roles will be listed: one for unauthenticated
users and one for authenticated users.
3. Click the role for unauthenticated users (it will have unauth appended to your Identity Pool name).
4. Click the Create Role Policy button, select Policy Generator, and then click the Select button.
5. On the Edit Permissions page, enter the settings shown in the following image. The Amazon
Resource Name (ARN) of an S3 bucket looks like arn:aws:s3:::examplebucket/* and is
composed of the region in which the bucket is located and the name of the bucket. The settings
shown below will give your identity pool full to access to all actions for the specified bucket.
56
Chapter 9. Store and Retrieve Files with Amazon S3
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
6. Click the Add Statement button and then the Next Step button.
7. The Wizard will show you the configuration that you generated. Click the Apply Policy button.
For more information on granting access to S3, see Granting Access to an Amazon S3 Bucket
(http://blogs.aws.amazon.com/security/post/Tx3VRSWZ6B3SHAV/Writing-IAM-Policies-How-to-grantaccess-to-an-Amazon-S3-bucket).
Upload Files from the Console
Let’s seed the S3 bucket with a test file. We could do this programmatically, but for now let’s just use the
console.
1. In the S3 console, in your bucket view, click Upload.
2. Click Add Files and select a test file to upload. For this tutorial, we’ll assume you’re uploading an
image called myImage.jpg.
3. With your test image selected, click Start Upload.
9.1.4 Create the S3 TransferManager Client
To use the S3 TransferManager, we first need to create a TransferManager client:
AWSS3TransferManager *transferManager = [AWSS3TransferManager defaultS3TransferManager];
The AWSS3TransferManager class is our entry point to the high-level S3 API.
9.2 Download an Object
To download a file from a bucket, we have to construct the request using
AWSS3TransferManagerDownloadRequest. We then pass this request to the download method
of our client.
9.2. Download an Object
57
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
In the following snippet, we create an NSURL that we’ll use for a download location. Then we create a new
download request object and set three properties on it: the bucket name, the key (the name of the object in
the bucket), and the URL where the file will be downloaded (downloadingFileURL):
// Construct the NSURL for the download location.
NSString *downloadingFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"do
NSURL *downloadingFileURL = [NSURL fileURLWithPath:downloadingFilePath];
// Construct the download request.
AWSS3TransferManagerDownloadRequest *downloadRequest = [AWSS3TransferManagerDownloadRequest
downloadRequest.bucket = @"myBucket";
downloadRequest.key = @"myImage.jpg";
downloadRequest.downloadingFileURL = downloadingFileURL;
Now we can pass the download request to the download: method of the TransferManager client. The
AWS Mobile SDK for iOS uses AWSTask to support asynchronous calls to Amazon Web Services. The
download: method is asynchronous and returns a AWSTask object, so we’ll use it accordingly:
// Download the file.
[[transferManager download:downloadRequest] continueWithExecutor:[AWSExecutor mainThreadExe
withBlock:^id(AWSTask *task) {
if (task.error){
if ([task.error.domain isEqualToString:AWSS3TransferManagerErrorDomain]) {
switch (task.error.code) {
case AWSS3TransferManagerErrorCancelled:
case AWSS3TransferManagerErrorPaused:
break;
default:
NSLog(@"Error: %@", task.error);
break;
}
} else {
// Unknown error.
NSLog(@"Error: %@", task.error);
}
}
if (task.result) {
AWSS3TransferManagerDownloadOutput *downloadOutput = task.result;
//File downloaded successfully.
}
return nil;
}];
In the example above, withBlock: is executed on the main thread.
We can display the downloaded image in a UIImageView. Assuming UIImageView has been
implemented, we can do this as follows:
self.imageView.image = [UIImage imageWithContentsOfFile:downloadingFilePath];
Note: in order for this image to display, we have to wait for the download to finish.
58
Chapter 9. Store and Retrieve Files with Amazon S3
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
9.3 Upload an Object
Uploading an object with the S3 TransferManager is similar to downloading one. First we construct a
request object and then pass that request object the TransferManager client. For the purposes of this
example, let’s say that we have an NSURL object, testFileURL, that represents the file we want to
upload. We can build the request using AWSS3TransferManagerUploadRequest, as shown below:
AWSS3TransferManagerUploadRequest *uploadRequest = [AWSS3TransferManagerUploadRequest new];
uploadRequest.bucket = @"myBucket";
uploadRequest.key = @"myTestFile.txt";
uploadRequest.body = testFileURL;
As with a download request, the key value will be the name of the object in the S3 bucket. The body
property of the request takes an NSURL object.
Having created the request, we can now pass it to the upload method of the TransferManager client. The
upload method returns a AWSTask object, so we’ll again use
continueWithExecutor:withBlock: to handle the upload:
[[transferManager upload:uploadRequest] continueWithExecutor:[AWSExecutor mainThreadExecuto
withBlock:^id(AWSTask *task) {
if (task.error) {
if ([task.error.domain isEqualToString:AWSS3TransferManagerErrorDomain]) {
switch (task.error.code) {
case AWSS3TransferManagerErrorCancelled:
case AWSS3TransferManagerErrorPaused:
break;
default:
NSLog(@"Error: %@", task.error);
break;
}
} else {
// Unknown error.
NSLog(@"Error: %@", task.error);
}
}
if (task.result) {
AWSS3TransferManagerUploadOutput *uploadOutput = task.result;
// The file uploaded successfully.
}
return nil;
}];
Note that upload: is an asynchronous method and returns immediately. Since it doesn’t block the
running thread, it’s safe to call this method on the main thread.
9.3. Upload an Object
59
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
9.4 Pause, Resume, and Cancel Object Transfers
The TransferManager supports pause, resume, and cancel operations for both uploads and downloads.
pause, cancel, resumeAll, cancelAll, pauseAll, upload:, and download: all return
instances of AWSTask. Thus, you should use these methods with a continueWithBlock to catch any
errors. For example, a pause operation might look like this:
[[self.uploadRequest pause] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"Error: %@",task.error);
} else {
//Pause the upload.
}
return nil;
}];
For the sake of brevity, the examples below omit the continueWithBlock.
To pause an object transfer, call pause on the request object:
[uploadRequest pause];
[downloadRequest pause];
To resume a transfer, call upload or download, as appropriate, and pass in the paused request:
[transferManager upload:uploadRequest];
[transferManager download:downloadRequest];
To cancel a transfer, call cancel on the upload or download request:
[uploadRequest cancel];
[downloadRequest cancel];
You can also perform pause, resume, and cancel operations in batches. To pause all of the current upload
and download requests, call pauseAll on the TransferManager:
[transferManager pauseAll];
To resume all of the current upload and download requests, call resumeAll on the TransferManager and
pass in an AWSS3TransferManagerResumeAllBlock, which can be used to reset the progress
blocks for the requests:
[transferManager resumeAll:^(AWSRequest *request) {
//Resume paused requests.
}];
To cancel all upload and download requests, call cancelAll on the TransferManager:
[transferManager cancelAll];
60
Chapter 9. Store and Retrieve Files with Amazon S3
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
9.5 Track Progress
Using the uploadProgress and downloadProgress blocks, you can track the progress of object
transfers. These blocks work in conjunction with the Grand Central Dispatch dispatch_async
function, as shown in the examples below.
Track the progress of an upload:
uploadRequest.uploadProgress = ^(int64_t bytesSent, int64_t totalBytesSent, int64_t totalB
dispatch_async(dispatch_get_main_queue(), ^{
//Update progress.
});
Track the progress of a download:
downloadRequest.downloadProgress = ^(int64_t bytesWritten, int64_t totalBytesWritten, int64
dispatch_async(dispatch_get_main_queue(), ^{
//Update progress
});
9.6 Multipart Upload
S3 provides a multipart upload feature that lets you upload a single object as a set of parts. Each part is a
contiguous portion of the object’s data, and the object parts are uploaded independently and in any order. If
transmission of any part fails, you can retransmit that part without affecting other parts. After all parts of
the object are uploaded, S3 assembles these parts and creates the object.
In the AWS Mobile SDK for iOS, the S3 TransferManager handles multipart upload for you. The
minimum part size for a multipart upload is 5MB.
9.7 Use Pre-Signed URLs to Transfer Objects in the Background
In certain cases—particularly if you’re working with large file transfers—you may want to perform uploads
and downloads in the background. To do this, you need to create a background session using
NSURLSession and then transfer your objects using pre-signed URLs.
The sections below discuss pre-signed S3 URLs. To learn more about NSURLSession, see Using
NSURLSession
(https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/Articles/UsingNSURLSessi
9.7.1 Pre-Signed URLs
By default, all S3 resources are private. If you want your users to have access to S3 objects or to an S3
bucket, you can assign appropriate permissions via an IAM policy
(http://docs.aws.amazon.com/IAM/latest/UserGuide/PoliciesOverview.html).
Alternatively, you can use pre-signed URLs to give your users access to S3 objects. A pre-signed URL
provides access to an object without requiring AWS security credentials or permissions.
9.5. Track Progress
61
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
When you create a pre-signed URL, you must provide your security credentials, specify a bucket name, an
object key, an HTTP method, and an expiration date and time. The pre-signed URL is valid only for the
specified duration.
9.7.2 Build a Pre-Signed URL
The following example shows how to build a pre-signed URL for an S3 download in the background:
AWSS3GetPreSignedURLRequest *getPreSignedURLRequest = [AWSS3GetPreSignedURLRequest new];
getPreSignedURLRequest.bucket = @"myBucket";
getPreSignedURLRequest.key = @"myImage.jpg";
getPreSignedURLRequest.HTTPMethod = AWSHTTPMethodGET;
getPreSignedURLRequest.expires = [NSDate dateWithTimeIntervalSinceNow:3600];
[[[AWSS3PreSignedURLBuilder defaultS3PreSignedURLBuilder] getPreSignedURL:getPreSignedURLRe
continueWithBlock:^id(AWSTask *task
if (task.error) {
NSLog(@"Error: %@",task.error);
} else {
NSURL *presignedURL = task.result;
NSLog(@"download presignedURL is: \n%@", presignedURL);
NSURLRequest *request = [NSURLRequest requestWithURL:presignedURL];
self.downloadTask = [self.session downloadTaskWithRequest:request];
//downloadTask is an instance of NSURLSessionDownloadTask.
//session is an instance of NSURLSession.
[self.downloadTask resume];
}
return nil;
}];
The example above uses GET as the HTTP method: AWSHTTPMethodGET. For an upload request to S3,
we would need to use a PUT method and also specify a content type:
getPreSignedURLRequest.HTTPMethod = AWSHTTPMethodPUT;
NSString *fileContentTypeStr = @"text/plain";
getPreSignedURLRequest.contentType = fileContentTypeStr;
Here’s an example of building a pre-signed URL for a background upload to S3:
AWSS3GetPreSignedURLRequest *getPreSignedURLRequest = [AWSS3GetPreSignedURLRequest new];
getPreSignedURLRequest.bucket = @"myBucket";
getPreSignedURLRequest.key = @"myFile";
getPreSignedURLRequest.HTTPMethod = AWSHTTPMethodPUT;
getPreSignedURLRequest.expires = [NSDate dateWithTimeIntervalSinceNow:3600];
//Important: set contentType for a PUT request.
NSString *fileContentTypeStr = @"text/plain";
getPreSignedURLRequest.contentType = fileContentTypeStr;
62
Chapter 9. Store and Retrieve Files with Amazon S3
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
[[[AWSS3PreSignedURLBuilder defaultS3PreSignedURLBuilder] getPreSignedURL:getPreSignedURLRe
continueWithBlock:^id(AWSTask *task
if (task.error) {
NSLog(@"Error: %@",task.error);
} else {
NSURL *presignedURL = task.result;
NSLog(@"upload presignedURL is: \n%@", presignedURL);
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:presignedURL];
request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
[request setHTTPMethod:@"PUT"];
[request setValue:fileContentTypeStr forHTTPHeaderField:@"Content-Type"];
self.uploadTask = [self.session uploadTaskWithRequest:request fromFile:self.uploadF
//uploadTask is an instance of NSURLSessionDownloadTask.
//session is an instance of NSURLSession.
[self.uploadTask resume];
}
return nil;
}];
9.8 Use Server-Side Encryption
The AWS Mobile SDK for iOS supports server-side encryption of Amazon S3 data. To learn more about
server-side encryption, see PUT Object
(http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html).
Use the following properties to configure the encryption:
• SSECustomerAlgorithm
(http://docs.aws.amazon.com/AWSiOSSDK/latest/Classes/AWSS3ReplicateObjectOutput.html#//api/name/SSECusto
• SSECustomerKey
(http://docs.aws.amazon.com/AWSiOSSDK/latest/Classes/AWSS3UploadPartRequest.html#//api/name/SSECustomer
• SSECustomerKeyMD5
(http://docs.aws.amazon.com/AWSiOSSDK/latest/Classes/AWSS3PutObjectOutput.html#//api/name/SSECustomerKe
• AWSS3ServerSideEncryption
(http://docs.aws.amazon.com/AWSiOSSDK/latest/Constants/AWSS3ServerSideEncryption.html)
To use these properties, you’ll need to import AWSSS3Model:
#import <AWSS3/AWSS3.h>
SSECustomerAlgorithm is a property of AWSS3ReplicateObjectOutput. If server-side
encryption with a customer-provided encryption key was requested, the response will include this header
9.8. Use Server-Side Encryption
63
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
confirming the encryption algorithm used. Currently, the only valid option is AES256. You can access
SSECustomerAlgorithm as follows:
AWSS3ReplicateObjectOutput *replicateObjectOutput = [AWSS3ReplicateObjectOutput new];
replicateObjectOutput.SSECustomerAlgorithm = @"mySseCustomerAlgorithm";
SSECustomerKey, a property of AWSS3UploadPartRequest, specifies the customer-provided
encryption key for Amazon S3 to use in encrypting data. This value is used to store the object, and then it’s
discarded; Amazon doesn’t store the encryption key. The key must be appropriate for use with the
algorithm specified in the x-amz-server-side-encryption-customer-algorithm header.
This must be the same encryption key specified in the request to initiate a multipart upload. You can access
SSECustomerKey as follows:
AWSS3UploadPartRequest *uploadPartRequest = [AWSS3UploadPartRequest new];
uploadPartRequest.SSECustomerKey = @"customerProvidedEncryptionKey";
SSECustomerKeyMD5 is a property of AWSS3PutObjectOutput. If server-side encryption with a
customer-provided encryption key is requested, the response will include this header to provide round trip
message integrity verification of the customer-provided encryption key. You can access
SSECustomerKeyMD5 as follows:
AWSS3PutObjectOutput *objectOutput = [AWSS3PutObjectOutput new];
//Access objectOutput.SSECustomerKeyMD5 ...
AWSS3ServerSideEncryption represents the encryption algorithm for storing an object in S3. You
can access it as follows:
AWSS3ReplicateObjectOutput *replicateObjectOutput = [AWSS3ReplicateObjectOutput new];
// Access replicateObjectOutput.serverSideEncryption ...
9.9 Additional Resources
• Amazon Simple Storage Service Getting Started Guide
(http://docs.aws.amazon.com/AmazonS3/latest/gsg/GetStartedWithS3.html)
• Amazon Simple Storage Service API Reference
(http://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html)
• Amazon Simple Storage Service Developer Guide
(http://docs.aws.amazon.com/AmazonS3/latest/dev/Welcome.html)
64
Chapter 9. Store and Retrieve Files with Amazon S3
CHAPTER 10
Amazon S3 Transfer Utility for iOS (Beta)
Amazon S3 Transfer Manager for iOS (Beta)
(http://docs.aws.amazon.com/mobile/sdkforios/developerguide/s3transfermanager.html#create-the-s3transfermanager-client) simplifies data transfer between your iOS app and Amazon S3. In addition to the
S3 Transfer Manager, there is an easier and more powerful way to transfer data between your iOS app and
Amazon S3, Amazon S3 Transfer Utility for iOS (Beta). This topic shows you how to get started with the
new Amazon S3 Transfer Utility.
The Amazon S3 Transfer Utility offers two main advantages over the S3 Transfer Manager:
• Ability to continue transferring data in the background
• An API to upload binary data without first requiring it be saved as a file. The S3 Transfer Manager
requires you to save data to a file before passing it to Transfer Manager.
10.1 Setting Up the S3 Transfer Utility
To set up the S3 Transfer Utility in your app, you must set up Amazon Cognito Identity to authenticate
calls to AWS from your app then configure your application delegate.
10.1.1 Setting Up Amazon Cognito Identity
First, you need to set up Amazon Cognito Identity.
Import the following header in your application delegate class.
#import <AWSS3/AWSS3.h>
Set up AWSCognitoCredentialsProvider in the application:didFinishLaunchingWithOptions: application delegate.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionar
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvide
initWithRegionType:AWSRegionUSEast1
identityPoolId:@"YourIdentityPoolId"];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] i
65
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
return YES;
}
Refer to Set Up the SDK for iOS
(http://docs.aws.amazon.com/mobile/sdkforios/developerguide/setup.html) and Amazon Cognito Identity
(http://docs.aws.amazon.com/mobile/sdkforios/developerguide/cognito-auth.html) sections of iOS
Developer Guide (http://docs.aws.amazon.com/mobile/sdkforios/developerguide/) for more details.
10.1.2 Configuring the Application Delegate
The Transfer Utility for iOS (Beta) uses the background transfer feature in iOS to continue data transfers
even when your app isn’t running.
Call the following class method in your application:handleEventsForBackgroundURLSession:completionHandler:
application delegate so that iOS can tell the Transfer Utility when the transfer finishes while the app is not
suspended.
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSStr
completionHandler:(void (^)())completionHandler {
/* Store the completion handler.*/
[AWSS3TransferUtility interceptApplication:application handleEventsForBackgroundURLSession:
}
10.2 Transferring Data
After you set up the S3 Transfer Utility, you can upload or download files and binary data between S3 and
your app.
10.2.1 Uploading a File
To upload a file call uploadFile:bucket:key:contentType:expression:completionHander: on
AWSS3TransferUtility:
NSURL *fileURL = // The file to upload.
AWSS3TransferUtility *transferUtility = [AWSS3TransferUtility defaultS3TransferUtility];
[[transferUtility uploadFile:fileURL
bucket:@"YourBucketName"
key:@"YourObjectKeyName"
contentType:@"text/plain"
expression:nil
completionHander:nil] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"Error: %@", task.error);
66
Chapter 10. Amazon S3 Transfer Utility for iOS (Beta)
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
}
if (task.exception) {
NSLog(@"Exception: %@", task.exception);
}
if (task.result) {
AWSS3TransferUtilityUploadTask *uploadTask = task.result;
// Do something with uploadTask.
}
return nil;
}];
If you want to know when the upload completes, you can pass a completion handler block. You can also
configure the upload behavior by passing AWSS3TransferUtilityUploadExpression. For
example, you can add a upload progress feedback block to the expression object. Here is a code snippet
containing the completion handler and upload progress feedback:
NSURL *fileURL = // The file to upload.
AWSS3TransferUtilityUploadExpression *expression = [AWSS3TransferUtilityUploadExpression ne
expression.uploadProgress = ^(AWSS3TransferUtilityTask *task, int64_t bytesSent, int64_t to
dispatch_async(dispatch_get_main_queue(), ^{
// Do something e.g. Update a progress bar.
});
};
AWSS3TransferUtilityUploadCompletionHandlerBlock completionHandler = ^(AWSS3TransferUtility
dispatch_async(dispatch_get_main_queue(), ^{
// Do something e.g. Alert a user for transfer completion.
// On failed uploads, `error` contains the error object.
});
};
AWSS3TransferUtility *transferUtility = [AWSS3TransferUtility defaultS3TransferUtility];
[[transferUtility uploadFile:fileURL
bucket:@"YourBucketName"
key:@"YourObjectKeyName"
contentType:@"text/plain"
expression:expression
completionHander:completionHandler] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"Error: %@", task.error);
}
if (task.exception) {
NSLog(@"Exception: %@", task.exception);
}
if (task.result) {
AWSS3TransferUtilityUploadTask *uploadTask = task.result;
// Do something with uploadTask.
}
return nil;
}];
10.2. Transferring Data
67
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
10.2.2 Uploading Binary Data
To upload an instance of NSData call uploadData:bucket:key:contentType:expression:completionHander:
NSData *dataToUpload = // The data to upload.
AWSS3TransferUtilityUploadExpression *expression = [AWSS3TransferUtilityUploadExpression ne
expression.uploadProgress = ^(AWSS3TransferUtilityTask *task, int64_t bytesSent, int64_t to
dispatch_async(dispatch_get_main_queue(), ^{
// Do something e.g. Update a progress bar.
});
};
AWSS3TransferUtilityUploadCompletionHandlerBlock completionHandler = ^(AWSS3TransferUtility
dispatch_async(dispatch_get_main_queue(), ^{
// Do something e.g. Alert a user for transfer completion.
// On failed uploads, `error` contains the error object.
});
};
AWSS3TransferUtility *transferUtility = [AWSS3TransferUtility defaultS3TransferUtility];
[[transferUtility uploadData:dataToUpload
bucket:@"YourBucketName"
key:@"YourObjectKeyName"
contentType:@"text/plain"
expression:expression
completionHander:completionHandler] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"Error: %@", task.error);
}
if (task.exception) {
NSLog(@"Exception: %@", task.exception);
}
if (task.result) {
AWSS3TransferUtilityUploadTask *uploadTask = task.result;
// Do something with uploadTask.
}
return nil;
}];
Note that this method saves the data as a file in a temporary directory. The next time
AWSS3TransferUtility is initialized, the expired temporary files are cleaned up. If you upload many
large objects to an Amazon S3 bucket in a short period of time, it’s better to use the upload file method then
manually purge the unnecessary temporary files as early as possible for more efficient use of disk space.
10.2.3 Downloading to a File
Here are code snippets you can use for downloading to a file.
68
Chapter 10. Amazon S3 Transfer Utility for iOS (Beta)
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
NSURL *fileURL = // The file URL of the download destination.
AWSS3TransferUtilityDownloadExpression *expression = [AWSS3TransferUtilityDownloadExpressio
expression.downloadProgress = ^(AWSS3TransferUtilityTask *task, int64_t bytesWritten, int64
dispatch_async(dispatch_get_main_queue(), ^{
// Do something e.g. Update a progress bar.
});
};
AWSS3TransferUtilityDownloadCompletionHandlerBlock completionHandler = ^(AWSS3TransferUtili
dispatch_async(dispatch_get_main_queue(), ^{
// Do something e.g. Alert a user for transfer completion.
// On successful downloads, `location` contains the S3 object file URL.
// On failed downloads, `error` contains the error object.
});
};
AWSS3TransferUtility *transferUtility = [AWSS3TransferUtility defaultS3TransferUtility];
[[transferUtility downloadToURL:nil
bucket:S3BucketName
key:S3DownloadKeyName
expression:expression
completionHander:completionHandler] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"Error: %@", task.error);
}
if (task.exception) {
NSLog(@"Exception: %@", task.exception);
}
if (task.result) {
AWSS3TransferUtilityDownloadTask *downloadTask = task.result;
// Do something with downloadTask.
}
return nil;
}];
10.2.4 Downloading as Binary Data
Here are code snippets you can use for downloading binary data.
AWSS3TransferUtilityDownloadExpression *expression = [AWSS3TransferUtilityDownloadExpressio
expression.downloadProgress = ^(AWSS3TransferUtilityTask *task, int64_t bytesWritten, int64
dispatch_async(dispatch_get_main_queue(), ^{
// Do something e.g. Update a progress bar.
});
};
AWSS3TransferUtilityDownloadCompletionHandlerBlock completionHandler = ^(AWSS3TransferUtili
dispatch_async(dispatch_get_main_queue(), ^{
// Do something e.g. Alert a user for transfer completion.
// On successful downloads, `data` contains the S3 object.
10.2. Transferring Data
69
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
// On failed downloads, `error` contains the error object.
});
};
AWSS3TransferUtility *transferUtility = [AWSS3TransferUtility defaultS3TransferUtility];
[[transferUtility downloadDataFromBucket:S3BucketName
key:S3DownloadKeyName
expression:expression
completionHander:completionHandler] continueWithBlock:^id(AWSTask *
if (task.error) {
NSLog(@"Error: %@", task.error);
}
if (task.exception) {
NSLog(@"Exception: %@", task.exception);
}
if (task.result) {
AWSS3TransferUtilityDownloadTask *downloadTask = task.result;
// Do something with downloadTask.
}
return nil;
}];
10.2.5 Transferring in the Background
All uploads and downloads continue in the background whether your app is active or in the background. If
iOS terminates your app while transfers are ongoing, the system continues the transfers in the background
then launches your app after the transfers finish. If the user terminates the app while transfers are ongoing,
those transfers stop.
You can’t persist blocks on disk so you need to rewire the completion handler and progress feedback
blocks when your app relaunches. You should call enumerateToAssignBlocksForUploadTask:downloadTask: on
AWSS3TransferUtility to reassign the blocks as needed. Here is an example of reassigning blocks.
- (void)viewDidLoad {
[super viewDidLoad];
...
AWSS3TransferUtility *transferUtility = [AWSS3TransferUtility defaultS3TransferUtility]
[transferUtility
enumerateToAssignBlocksForUploadTask:^(AWSS3TransferUtilityUploadTask *uploadTask, __a
NSLog(@"%lu", (unsigned long)uploadTask.taskIdentifier);
// Use `uploadTask.taskIdentifier` to determine what blocks to assign.
*uploadProgressBlockReference = // Reassign your progress feedback block.
*completionHandlerReference = // Reassign your completion handler.
}
downloadTask:^(AWSS3TransferUtilityDownloadTask *downloadTask, __autoreleasing AWSS3Tr
70
Chapter 10. Amazon S3 Transfer Utility for iOS (Beta)
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
NSLog(@"%lu", (unsigned long)downloadTask.taskIdentifier);
// Use `downloadTask.taskIdentifier` to determine what blocks to assign.
*downloadProgressBlockReference = // Reassign your progress feedback block.
*completionHandlerReference = // Reassign your completion handler.
}];
}
You receive AWSS3TransferUtilityUploadTask and
AWSS3TransferUtilityDownloadTask when you initiate the upload and download respectively.
For upload:
if (task.result) {
AWSS3TransferUtilityUploadTask *uploadTask = task.result;
// Do something with uploadTask.
}
For download:
if (task.result) {
AWSS3TransferUtilityDownloadTask *downloadTask = task.result;
// Do something with downloadTask.
}
They have a property called taskIdentifier, which uniquely identifies the transfer task object within
the Transfer Utility. You may need to persist the identifier so that you can uniquely identify the
upload/download task objects when rewiring the blocks for app relaunch.
10.3 Managing Data Transfers
In order to suspend, resume, and cancel uploads and downloads, you need to retain references to
AWSS3TransferUtilityUploadTask and AWSS3TransferUtilityDownloadTask.
To manage data transfers call - suspend, - resume, and - cancel on
AWSS3TransferUtilityUploadTask and AWSS3TransferUtilityDownloadTask.
10.4 Limitations
The S3 Transfer Utility generates Amazon S3 Pre-Signed URLs to use for background data transfer. Using
Amazon Cognito Identity, you receive AWS temporary credentials that are valid up to 60 minutes. At the
same time, generated S3 pre-signed URLs cannot last longer than that time. Because of this limitation, the
S3 Transfer Utility enforces 50 minute transfer timeouts, leaving a 10 minute buffer before AWS temporary
credentials are regenerated. After 50 minutes, you receive a transfer failure.
If you need to transfer data that cannot be transferred in under 50 minutes, use
AWSS3TransferManager instead.
10.3. Managing Data Transfers
71
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
72
Chapter 10. Amazon S3 Transfer Utility for iOS (Beta)
CHAPTER 11
Store and Retrieve App Data in Amazon DynamoDB
Amazon DynamoDB (http://aws.amazon.com/dynamodb/) is a fast, highly scalable, highly available,
cost-effective, nonrelational database service. DynamoDB removes traditional scalability limitations on
data storage while maintaining low latency and predictable performance.
The AWS Mobile SDK for iOS provides both low-level and high-level libraries for working with
DynamoDB. The high-level library includes the DynamoDB Object Mapper, which lets you map
client-side classes to DynamoDB tables; perform various create, read, update, and delete (CRUD)
operations; and execute queries. Using the DynamoDB Object Mapper, you can write simple, readable
code that stores objects in the cloud.
Most of the tasks described below are accomplished with the DynamoDB Object Mapper. Conditional
writes and batch operations are accomplished with the low-level client (see Conditional Writes Using the
Low-Level Client (page 82) and Batch Operations Using the Low-Level Client (page 83)).
For information about DynamoDB Region availability, see AWS Service Region Availability
(http://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/).
11.1 Getting Started
This section provides a step-by-step guide for getting started with DynamoDB using the AWS Mobile SDK
for iOS. You can also try out the DynamoDB sample
(https://github.com/awslabs/aws-sdk-ios-samples/tree/master/DynamoDBObjectMapper-Sample).
11.1.1 Get the SDK
To use DynamoDB from your mobile app, first set up the AWS Mobile SDK for iOS:
1. Download the iOS SDK and include it in your iOS project, as described at Set Up the SDK for iOS
(page 27).
2. Import the following header into your project:
#import <AWSDynamoDB/AWSDynamoDB.h>
73
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
11.1.2 Configure Credentials
Amazon Cognito lets you create unique end user identifiers for accessing AWS cloud services. You’ll use
Cognito to provide temporary AWS credentials to your app.
1. Log in to the Cognito console (https://console.aws.amazon.com/cognito/).
2. Create an identity pool. For this tutorial, you don’t need to configure public identity providers,
OpenID Connect providers, or developer authenticated identities. But do enable unauthenticated
identities.
3. Cognito creates and assigns new IAM roles for you. When you have the option, select Update Roles.
4. Copy the auto-generated Cognito client initialization code into your project. For this tutorial, you
won’t need the store-and-synchronize snippet.
For more information on setting up the Cognito client, see Cognito Identity Developer Guide
(http://docs.aws.amazon.com/cognito/devguide/identity/).
11.1.3 Create a DynamoDB Table and Index
For this tutorial, let’s assume we’re building a bookstore app. Our app will need to keep track of the books
available in the bookstore, and we can create a DynamoDB table to do so.
To create our Books table:
1. Log in to the DynamoDB console (https://console.aws.amazon.com/dynamodb/).
2. Click Create Table.
3. Enter Books as the name of the table.
4. Select Hash as the primary key type.
5. For the hash attribute name, ensure that String is selected and enter ISBN. Click Continue.
6. With the index type set to Global Secondary Index and the data type set to String, enter Author in
the Index Hash Key field.
7. In the Index Range Key field, with the data type set to Number, enter Price.
8. In the Index Name field enter Author-Price-index.
9. Leave the other values at their defaults and click Add Index to Table and then Continue.
10. Set the read capacity to 10 and the write capacity to 5. Click Continue.
11. Enter a notification email and click Continue to create throughput alarms.
12. Click Create. DynamoDB will create your database.
13. Refresh the console and select your Books table from the list of tables.
14. Open the Details tab and copy or note the Amazon Resource Name (ARN). You’ll need this in a
moment.
74
Chapter 11. Store and Retrieve App Data in Amazon DynamoDB
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
11.1.4 Set Permissions
To use DynamoDB in an application, you must set the correct permissions. The following IAM policy
allows the user to perform the actions shown in this tutorial on two resources (a table and an index)
identified by ARN (http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html):
{
"Statement": [{
"Effect": "Allow",
"Action": [
"dynamodb:DeleteItem",
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:Scan",
"dynamodb:Query",
"dynamodb:UpdateItem",
"dynamodb:BatchWriteItem"
],
"Resource": [
"arn:aws:dynamodb:us-west-2:123456789012:table/Books",
"arn:aws:dynamodb:us-west-2:123456789012:table/Books/index/*"
]
}]
}
Apply this policy to the unauthenticated role assigned to your Cognito identity pool, replacing the
Resource values with the correct ARN for your DynamoDB table:
1. Log in to the IAM console (https://console.aws.amazon.com/iam).
2. Select Roles and select the “Unauth” role that Cognito created for you.
3. Click Attach Role Policy.
4. Select Custom Policy and click Select.
5. Enter a name for your policy and paste in the policy document shown above, replacing the
Resource values with the ARNs for your table and index. (You can retrieve the table ARN from
the Details tab of the database; then append /index/* to obtain the value for the index ARN.
6. Click Apply Policy.
To learn more about IAM policies, see Using IAM
(http://docs.aws.amazon.com/IAM/latest/UserGuide/IAM_Introduction.html). To learn more about
DynamoDB-specific policies, see Using IAM to Control Access to DynamoDB Resources
(http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/UsingIAMWithDDB.html).
11.1.5 Create a DynamoDB Object Mapper Client
We’re going to use the AWSDynamoDBObjectMapper
(http://docs.aws.amazon.com/AWSiOSSDK/latest/Classes/AWSDynamoDBObjectMapper.html) to map a
client-side class to our database. The Object Mapper supports high-level operations like creating, getting,
querying, updating, and deleting records. We can create an Object Mapper as follows:
11.1. Getting Started
75
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
AWSDynamoDBObjectMapper *dynamoDBObjectMapper = [AWSDynamoDBObjectMapper defaultDynamoDBObj
All of the Object Mapper methods return an AWSTask object, so you’ll need to work with AWSTask in
order to use DynamoDB effectively. To learn how to use the AWSTask class, see Working with AWSTask
(page 35).
11.2 Define a Mapping Class
In DynamoDB, a database is a collection of tables, and a table can be described as follows:
• A table is a collection of items.
• Each item is a collection of attributes.
• Each attribute has a name and a value.
For our bookstore app, each item in the table will represent a book, and each item will have four attributes:
Title, Author, Price, and ISBN.
Each item (Book) in the table will have a hash key—in this case, ISBN—which is the primary key for the
table.
We’re going to map each item in the Book table to a Book object in the client-side code, so that we can
directly manipulate the database item through its object representation.
Here’s the header for our Book class:
#import <Foundation/Foundation.h>
#import <AWSDynamoDB/AWSDynamoDB.h>
@interface Book : AWSDynamoDBObjectModel <AWSDynamoDBModeling>
@property
@property
@property
@property
(nonatomic,
(nonatomic,
(nonatomic,
(nonatomic,
strong)
strong)
strong)
strong)
NSString
NSString
NSNumber
NSString
*Title;
*Author;
*Price;
*ISBN;
@end
Note that the case of each attribute name in the mapping class must match the case of the corresponding
attribute name in DynamoDB. Otherwise, they’ll be treated as different attributes.
Note: As of SDK version 2.0.16, the AWSDynamoDBModel mapping class is deprecated and replaced by
AWSDynamoDBObjectModel. The deprecated AWSDynamoDBModel used NSArray to represent
multi-valued types (String Set, Number Set, and Binary Set); it did not support Boolean, Map, or List
types. The new AWSDynamoDBObjectModel uses NSSet for multi-valued types and supports
Boolean, Map, and List. For the Boolean type, you have to create an NSNumber using [NSNumber
numberWithBool:YES] or using the shortcuts @YES and @NO. For the Map type, create using
NSDictionary. For the List type, create using NSArray.
Here’s the implementation of our model:
76
Chapter 11. Store and Retrieve App Data in Amazon DynamoDB
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
#import <AWSDynamoDB/AWSDynamoDB.h>
#import "Book.h"
@implementation Book
+ (NSString *)dynamoDBTableName {
return @"Books";
}
+ (NSString *)hashKeyAttribute {
return @"ISBN";
}
@end
To conform to AWSDynamoDBModeling, we have to implement dynamoDBTableName and
hashKeyAttribute. dynamoDBTableName should return the name of the table, and
hashKeyAttribute should return the name of the hash key. If the table had a range key, we would also
need to implement + (NSString *)rangeKeyAttribute.
11.3 Interact with Stored Objects
Now that we have a DynamoDB table, a mapping class, and an Object Mapper client, we can start
interacting with objects in the cloud.
11.3.1 Save an Item
The save:
(http://docs.aws.amazon.com/AWSiOSSDK/latest/Classes/AWSDynamoDBObjectMapper.html#//api/name/save:)
method saves an object to DynamoDB, using the default configuration. save: takes as a parameter an
object that inherits from AWSDynamoDBObjectModel and conforms to the AWSDynamoDBModeling
protocol. The properties of this object will be mapped to attributes in the DynamoDB table.
First, we create the object that we want to save:
Book *myBook = [Book new];
myBook.ISBN = @"3456789012";
myBook.Title = @"The Scarlet Letter";
myBook.Author = @"Nathaniel Hawthorne";
myBook.Price = [NSNumber numberWithInt:899];
And then we pass the object to the save: method:
[[dynamoDBObjectMapper save:myBook]
continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"The request failed. Error: [%@]", task.error);
}
if (task.exception) {
NSLog(@"The request failed. Exception: [%@]", task.exception);
11.3. Interact with Stored Objects
77
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
}
if (task.result) {
//Do something with the result.
}
return nil;
}];
Save Behavior Options
The AWS Mobile SDK for iOS supports the following save behavior options:
• AWSDynamoDBObjectMapperSaveBehaviorUpdate: Does not affect unmodeled attributes
on a save operation; passing a nil value for the modeled attribute will remove it from the
corresponding item in DynamoDB. By default, the Object Mapper uses this behavior.
• AWSDynamoDBObjectMapperSaveBehaviorUpdateSkipNullAttributes: Similar to
the default update behavior, except that it ignores any null value attribute(s) and will NOT remove
them from an item in DynamoDB.
• AWSDynamoDBObjectMapperSaveBehaviorAppendSet: Treats scalar attributes (String,
Number, Binary) the same as the SkipNullAttributes option above. However, for set
attributes, it appends to the existing attribute value instead of overriding it. The caller needs to make
sure that the modeled attribute type matches the existing set type; otherwise, a service exception will
occur.
• AWSDynamoDBObjectMapperSaveBehaviorClobber: Clears and replaces all attributes,
including unmodeled ones, on save. Versioned field constraints will also be disregarded.
Here’s an example of setting a default save behavior on the Object Mapper:
AWSDynamoDBObjectMapperConfiguration *updateMapperConfig = [AWSDynamoDBObjectMapperConfigur
updateMapperConfig.saveBehavior = AWSDynamoDBObjectMapperSaveBehaviorUpdate_Skip_Null_Attri
// Update_Skip_Null_Attributes
Then we can use updateMapperConfig as an argument when calling save:configuration:
(http://docs.aws.amazon.com/AWSiOSSDK/latest/Classes/AWSDynamoDBObjectMapper.html#//api/name/save:configurati
11.3.2 Retrieve an Item
Using an object’s primary key (in this case, the hash attribute “ISBN”), we can load the corresponding item
from the database. The following code snippet returns the Book item with an ISBN of “6543210987”:
[[dynamoDBObjectMapper load:[Book class] hashKey:@"6543210987" rangeKey:nil]
continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"The request failed. Error: [%@]", task.error);
}
if (task.exception) {
NSLog(@"The request failed. Exception: [%@]", task.exception);
}
if (task.result) {
78
Chapter 11. Store and Retrieve App Data in Amazon DynamoDB
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
Book *book = task.result;
//Do something with the result.
}
return nil;
}];
The Object Mapper creates a mapping between the Book item returned from the database and the Book
object on the client (here, resultBook). Thus, assuming that the Book item has a title, we could access
the title at resultBook.Title.
Note that our Books database does not have a range key, so we passed nil to the rangeKey parameter.
11.3.3 Update an Item
To update an item in the database, just set new attributes and save the object again.
Note that setting a new hash key creates a new item in the database, even though it doesn’t create a new
object on the client. For example, we saved a book titled “The Scarlet Letter” with an ISBN of
3456789012. The ISBN is the hash key for the table. Let’s assume that we still have a myBook reference to
this Book instance. If we assign a new value to myBook.ISBN and save the object, we’ll have two books
in the database titled “The Scarlet Letter”—one with the old ISBN value, and one with the new value.
11.3.4 Delete an Item
To delete a table row, use the remove: method:
Book *bookToDelete = [Book new];
bookToDelete.ISBN = @"4456789012";
[[dynamoDBObjectMapper remove:bookToDelete]
continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"The request failed. Error: [%@]", task.error);
}
if (task.exception) {
NSLog(@"The request failed. Exception: [%@]", task.exception);
}
if (task.result) {
//Item deleted.
}
return nil;
}];
11.4 Perform a Scan
With a scan operation, we can retrieve all items from a given table. A scan examines every item in the table
and returns the results in an undetermined order.
11.4. Perform a Scan
79
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
The scan:expression: method takes two parameters—the class of the resulting object and an
instance of AWSDynamoDBScanExpression, which provides options for filtering results. In the
following example, we create an AWSDynamoDBScanExpression object and set its limit property.
Then we pass our Book class and the expression object to scan:expression::
AWSDynamoDBScanExpression *scanExpression = [AWSDynamoDBScanExpression new];
scanExpression.limit = @10;
[[dynamoDBObjectMapper scan:[Book class]
expression:scanExpression]
continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"The request failed. Error: [%@]", task.error);
}
if (task.exception) {
NSLog(@"The request failed. Exception: [%@]", task.exception);
}
if (task.result) {
AWSDynamoDBPaginatedOutput *paginatedOutput = task.result;
for (Book *book in paginatedOutput.items) {
//Do something with book.
}
}
return nil;
}];
The output of a scan is returned as an AWSDynamoDBPaginatedOutput object. We can access the
array of returned items via the items property.
The scanExpression method provides several optional parameters. For example, you can optionally
use a filter expression to filter the scan result. With a filter expression, you can specify a condition, attribute
names, and values on which you want the condition evaluated. For more information about the parameters
and the API, see AWSDynamoDBScanExpression:
(http://docs.aws.amazon.com/AWSiOSSDK/latest/Classes/AWSDynamoDBScanExpression.html).
The following code snippet scans the Books table to find books with price less than 50:
AWSDynamoDBScanExpression *scanExpression = [AWSDynamoDBScanExpression new];
scanExpression.limit = @10;
scanExpression.filterExpression = @"Price < :val";
scanExpression.expressionAttributeValues = @{@":val":@50};
[[dynamoDBObjectMapper scan:[Book class]
expression:scanExpression]
continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"The request failed. Error: [%@]", task.error);
}
if (task.exception) {
NSLog(@"The request failed. Exception: [%@]", task.exception);
}
if (task.result) {
AWSDynamoDBPaginatedOutput *paginatedOutput = task.result;
for (Book *book in paginatedOutput.items) {
80
Chapter 11. Store and Retrieve App Data in Amazon DynamoDB
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
//Do something with book.
}
}
return nil;
}];
You can also use the projectionExpression property to specify the attributes to retrieve from the
Books table. For example adding scanExpression.projectionExpression = @"ISBN,
Title, Price"; in the previous code snippet retrieves only those three properties in the book object.
The Author property in the book object will always be nil.
Scan is an expensive operation and should be used with care to avoid disrupting higher priority traffic on
the table. The Amazon DynamoDB Developer Guide has Guidelines for Query and Scan
(http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html) that explain best
practices for scan operations.
11.5 Perform a Query
The Query API enables you to query a table or a secondary index. You must provide a hash key value in
AWSDynamoDBQueryExpression. To query an index, you must also specify the indexName. You
must specify the hashKeyAttribute if you query a global secondary with a different hashKey. If the
table or index has a range key, you can optionally refine the results by providing a range key value and a
condition. The query:expression: method takes two parameters—the class of the resulting object
and an instance of AWSDynamoDBQueryExpression. In the following example, we query the Books
index table to find all books with author of “John Smith” and price less than 50:
AWSDynamoDBQueryExpression *queryExpression = [AWSDynamoDBQueryExpression new];
queryExpression.indexName = @"Author-Price-index";
queryExpression.hashKeyAttribute = @"Author";
queryExpression.hashKeyValues = @"John Smith";
queryExpression.rangeKeyConditionExpression = @"Price < :val";
queryExpression.expressionAttributeValues = @{@":val":@50};
[[dynamoDBObjectMapper query:[Book class]
expression:queryExpression]
continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"The request failed. Error: [%@]", task.error);
}
if (task.exception) {
NSLog(@"The request failed. Exception: [%@]", task.exception);
}
if (task.result) {
AWSDynamoDBPaginatedOutput *paginatedOutput = task.result;
for (Book *book in paginatedOutput.items) {
//Do something with book.
}
11.5. Perform a Query
81
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
}
return nil;
}];
In preceding code, indexName was specified since we are querying a index. We must also specify the
hashKeyAttribute since the hashKeyAttribute name of the global secondary index is different
from the table. We optionally specified rangeKeyConditionExpression and
expressionAttributeValues to refine the query to only retrieve items with Price less than 50. We
can also provide filterExpression and projectionExpression in
AWSDynamoDBQueryExpression. The syntax is the same as that used in a scan operation.
For more information, see AWSDynamoDBQueryExpression
(http://docs.aws.amazon.com/AWSiOSSDK/latest/Classes/AWSDynamoDBQueryExpression.html).
11.6 Conditional Writes Using the Low-Level Client
In a multi-user environment, multiple clients can access the same item and attempt to modify its attribute
values at the same time. To help clients coordinate writes to data items, the DynamoDB low-level client
supports conditional writes for PutItem, DeleteItem, and UpdateItem operations. With a
conditional write, an operation succeeds only if the item attributes meet one or more expected conditions;
otherwise, it returns an error.
In the following example, we update the price of an item in the Books table if the item has a “Price” value
of “999”:
AWSDynamoDB *dynamoDB = [AWSDynamoDB defaultDynamoDB];
AWSDynamoDBUpdateItemInput *updateInput = [AWSDynamoDBUpdateItemInput new];
AWSDynamoDBAttributeValue *hashKeyValue = [AWSDynamoDBAttributeValue new];
hashKeyValue.S = @"4567890123";
updateInput.tableName = @"Books";
updateInput.key = @{ @"ISBN" : hashKeyValue };
AWSDynamoDBAttributeValue *oldPrice = [AWSDynamoDBAttributeValue new];
oldPrice.N = @"999";
AWSDynamoDBExpectedAttributeValue *expectedValue = [AWSDynamoDBExpectedAttributeValue new];
expectedValue.value = oldPrice;
AWSDynamoDBAttributeValue *newPrice = [AWSDynamoDBAttributeValue new];
newPrice.N = @"1199";
AWSDynamoDBAttributeValueUpdate *valueUpdate = [AWSDynamoDBAttributeValueUpdate new];
valueUpdate.value = newPrice;
valueUpdate.action = AWSDynamoDBAttributeActionPut;
updateInput.attributeUpdates = @{@"Price": valueUpdate};
updateInput.expected = @{@"Price": expectedValue};
updateInput.returnValues = AWSDynamoDBReturnValueUpdatedNew;
82
Chapter 11. Store and Retrieve App Data in Amazon DynamoDB
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
[[dynamoDB updateItem:updateInput]
continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"The request failed. Error: [%@]", task.error);
}
if (task.exception) {
NSLog(@"The request failed. Exception: [%@]", task.exception);
}
if (task.result) {
//Do something with result.
}
return nil;
}];
Note that conditional writes are idempotent. This means that you can send the same conditional write
request multiple times, but it will have no further effect on the item after the first time DynamoDB
performs the specified update. In the example above, sending the same request a second time would result
in a ConditionalCheckFailedException, because the expected condition would no longer be
met after the first update.
11.7 Batch Operations Using the Low-Level Client
The DynamoDB low-level client provides batch write operations to put items in the database and delete
items from the database. You can also use batch get operations to return the attributes of one or more items
from one or more tables
The following example illustrates a batch write operation:
AWSDynamoDB *dynamoDB = [AWSDynamoDB defaultDynamoDB];
//Write Request 1
AWSDynamoDBAttributeValue *hashValue1 = [AWSDynamoDBAttributeValue new];
hashValue1.S = @"3210987654";
AWSDynamoDBAttributeValue *otherValue1 = [AWSDynamoDBAttributeValue new];
otherValue1.S = @"Some Title";
AWSDynamoDBWriteRequest *writeRequest = [AWSDynamoDBWriteRequest new];
writeRequest.putRequest = [AWSDynamoDBPutRequest new];
writeRequest.putRequest.item = @{
@"ISBN" : hashValue1,
@"Title" : otherValue1
};
//Write Request 2
AWSDynamoDBAttributeValue *hashValue2 = [AWSDynamoDBAttributeValue new];
hashValue2.S = @"8901234567";
AWSDynamoDBAttributeValue *otherValue2 = [AWSDynamoDBAttributeValue new];
otherValue2.S = @"Another Title";
AWSDynamoDBWriteRequest *writeRequest2 = [AWSDynamoDBWriteRequest new];
writeRequest2.putRequest = [AWSDynamoDBPutRequest new];
11.7. Batch Operations Using the Low-Level Client
83
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
writeRequest2.putRequest.item = @{
@"ISBN" : hashValue2,
@"Title" : otherValue2
};
AWSDynamoDBBatchWriteItemInput *batchWriteItemInput = [AWSDynamoDBBatchWriteItemInput new];
batchWriteItemInput.requestItems = @{@"Books": @[writeRequest,writeRequest2]};
[[dynamoDB batchWriteItem:batchWriteItemInput]
continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"The request failed. Error: [%@]", task.error);
}
if (task.exception) {
NSLog(@"The request failed. Exception: [%@]", task.exception);
}
if (task.result) {
//Do something with the result.
}
return nil;
}];
11.8 Additional Resources
• Amazon DynamoDB Developer Guide
(http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/)
• Amazon DynamoDB API Reference
(http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/)
84
Chapter 11. Store and Retrieve App Data in Amazon DynamoDB
CHAPTER 12
Process Streaming Data with Amazon Kinesis and Amazon Kinesis
Firehose
Amazon Kinesis is a fully managed service for real-time processing of streaming data at massive scale.
The SDK for iOS provides two high-level client classes, AWSKinesisRecorder and
AWSFirehoseRecorder, designed to help you interface with Amazon Kinesis and Amazon Kinesis
Firehose.
The Amazon Kinesis AWSKinesisRecorder client lets you store PutRecord
(http://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutRecord.html) requests on disk and then
send them all at once. This is useful because many mobile applications that use Amazon Kinesis will create
multiple PutRecord requests per second. Sending an individual request for each PutRecord action
could adversely impact battery life. Moreover, the requests could be lost if the device goes offline. Thus,
using the high-level Amazon Kinesis client for batching can preserve both battery life and data.
The Amazon Kinesis Firehose AWSFirehoseRecorder client lets you store PutRecords
(http://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutRecords.html) requests on disk and then
send them using PutRecordBatch.
For information about Amazon Kinesis Region availability, see AWS Service Region Availability
(http://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/).
12.1 What is Amazon Kinesis?
Amazon Kinesis (http://aws.amazon.com/kinesis/) is a fully managed service for real-time processing of
streaming data at massive scale. Amazon Kinesis can collect and process hundreds of terabytes of data per
hour from hundreds of thousands of sources, so you can write applications that process information in
real-time. With Amazon Kinesis applications, you can build real-time dashboards, capture exceptions and
generate alerts, drive recommendations, and make other real-time business or operational decisions. You
can also easily send data to other services such as Amazon Simple Storage Service, Amazon DynamoDB,
and Amazon Redshift.
85
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
12.2 What is Amazon Kinesis Firehose?
Amazon Kinesis Firehose (http://aws.amazon.com/kinesis/firehose/) is a fully managed service for
delivering real-time streaming data to destinations such as Amazon Simple Storage Service (Amazon S3)
and Amazon Redshift. With Firehose, you do not need to write any applications or manage any resources.
You configure your data producers to send data to Firehose and it automatically delivers the data to the
destination that you specified.
For more information about Amazon Kinesis Firehose, see Amazon Kinesis Firehose
(http://docs.aws.amazon.com/firehose/latest/dev/what-is-this-service.html).
You can also learn more about how the Kinesis services work together on the following page: Amazon
Kinesis services (http://aws.amazon.com/kinesis/).
12.3 Integrating Amazon Kinesis and Amazon Kinesis Firehose
To use the Amazon Kinesis mobile client, you’ll need to integrate the SDK for iOS into your app and
import the necessary libraries. To do so, follow these steps:
If you haven’t already done so, download the SDK for iOS (http://aws.amazon.com/mobile/sdk/), unzip it,
and include it in your application as described at Set Up the SDK for iOS (page 27). The instructions direct
you to import the headers for the services you’ll be using. For this example, you need the following import:
#import <AWSKinesis/AWSKinesis.h>
You can use Amazon Cognito to provide temporary AWS credentials to your application.
These credentials let the app access your AWS resources. To create a credentials provider, follow the
instructions at Cognito Identity Developer Guide (http://docs.aws.amazon.com/cognito/devguide/identity/).
To use Amazon Kinesis in an application, you must set the correct permissions. The following IAM policy
allows the user to submit records to a specific Amazon Kinesis stream, which is identified by ARN
(http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html):
{
"Statement": [{
"Effect": "Allow",
"Action": "kinesis:PutRecords",
"Resource": "arn:aws:kinesis:us-west-2:111122223333:stream/mystream"
}]
}
The following IAM policy allows the user to submit records to a specific Amazon Kinesis Firehose stream:
{
"Statement": [{
"Effect": "Allow",
"Action": "firehose:PutRecordBatch",
"Resource": "arn:aws:firehose:us-west-2:111122223333:deliverystream/mystream"
}]
}
86
Chapter 12. Process Streaming Data with Amazon Kinesis and Amazon Kinesis Firehose
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
This policy should be applied to roles assigned to the Cognito identity pool, but you will need to replace
the Resource value with the correct ARN for your Amazon Kinesis or Amazon Kinesis Firehose stream.
You can apply policies at the IAM console (https://console.aws.amazon.com/iam/). To learn more about
IAM policies, see Using IAM
(http://docs.aws.amazon.com/IAM/latest/UserGuide/IAM_Introduction.html).
To learn more about Amazon Kinesis-specific policies, see Controlling Access to Amazon Kinesis
Resources with IAM (http://docs.aws.amazon.com/kinesis/latest/dev/kinesis-using-iam.html).
To learn more about Amazon Kinesis Firehose policies, see Controlling Access with Amazon Kinesis
Firehose (http://docs.aws.amazon.com/firehose/latest/dev/controlling-access.html).
Once you have credentials, you can use AWSKinesisRecorder with Amazon Kinesis. The following
snippet returns a shared instance of the Amazon Kinesis service client:
AWSKinesisRecorder *kinesisRecorder = [AWSKinesisRecorder defaultKinesisRecorder];
You can use AWSFirehoseRecorder with Amazon Kinesis Firehose. The following snippet returns a
shared instance of the Amazon Kinesis Firehose service client:
AWSFirehoseRecorder *firehoseRecorder = [AWSFirehoseRecorder defaultFirehoseRecorder];
You can configure AWSKinesisRecorder or AWSFirehoseRecorder through their properties:
kinesisRecorder.diskAgeLimit = 30 * 24 * 60 * 60; // 30 days
kinesisRecorder.diskByteLimit = 10 * 1024 * 1024; // 10MB
kinesisRecorder.notificationByteThreshold = 5 * 1024 * 1024; // 5MB
The diskAgeLimit property sets the expiration for cached requests. When a request exceeds the limit,
it’s discarded. The default is no age limit. The diskByteLimit property holds the limit of the disk
cache size in bytes. If the storage limit is exceeded, older requests are discarded. The default value is 5
MB. Setting the value to 0 means that there’s no practical limit. The notficationByteThreshold
property sets the point beyond which Kinesis issues a notification that the byte threshold has been reached.
The default value is 0, meaning that by default Amazon Kinesis doesn’t post the notification.
To see how much local storage is being used for Amazon Kinesis PutRecord requests, check the
diskBytesUsed property.
With AWSKinesisRecorder created and configured, you can use saveRecord:streamName: to
save records to local storage.
NSData *yourData = [@"Test_data" dataUsingEncoding:NSUTF8StringEncoding];
[kinesisRecorder saveRecord:yourData streamName:@"YourStreamName"]
In the preceding example, we create an NSData object and save it locally. YourStreamName should be a
string corresponding to the name of your Kinesis stream. You can create new streams in the Amazon
Kinesis console (https://console.aws.amazon.com/kinesis/).
Here is a similar snippet for Amazon Kinesis Firehose:
NSData *yourData = [@"Test_data" dataUsingEncoding:NSUTF8StringEncoding];
[firehoseRecorder saveRecord:yourData streamName:@"YourStreamName"]
To submit all the records stored on the device, call submitAllRecords.
12.3. Integrating Amazon Kinesis and Amazon Kinesis Firehose
87
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
[kinesisRecorder submitAllRecords];
[firehoseRecorder submitAllRecords];
submitAllRecords sends all locally saved requests to the Amazon Kinesis service. Requests that are
successfully sent will be deleted from the device. Requests that fail because the device is offline will be
kept and submitted later. Invalid requests are deleted.
Both saveRecord and submitAllRecords are asynchronous operations, so you should ensure that
saveRecord is complete before you invoke submitAllRecords. The following code sample shows
the methods used correctly together:
// Create an array to store a batch of objects.
NSMutableArray *tasks = [NSMutableArray new];
for (int32_t i = 0; i < 100; i++) {
[tasks addObject:[kinesisRecorder saveRecord:[[NSString stringWithFormat:@"TestString-%
streamName:@"YourStreamName"]];
}
[[[AWSTask taskForCompletionOfAllTasks:tasks] continueWithSuccessBlock:^id(AWSTask *task) {
return [kinesisRecorder submitAllRecords];
}] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"Error: [%@]", task.error);
}
return nil;
}];
To learn more about working with Amazon Kinesis, see the Amazon Kinesis Developer Resources
(http://aws.amazon.com/kinesis/developer-resources/).
To learn more about the Amazon Kinesis classes, see the class reference for AWSKinesisRecorder
(http://docs.aws.amazon.com/AWSiOSSDK/latest/Classes/AWSKinesisRecorder.html).
For information about AWS service region availability, see AWS Service Region Availability
(http://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/).
88
Chapter 12. Process Streaming Data with Amazon Kinesis and Amazon Kinesis Firehose
CHAPTER 13
Execute Code On Demand with Amazon Lambda
Amazon Lambda is a compute service that runs your code in response to events and automatically manages
the compute resources for you, making it easy to build applications that respond quickly to new
information. Amazon Lambda functions can be called directly from mobile, IoT, and Web apps and send a
response back synchronously, making it easy to create scalable, secure, and highly available backends for
your mobile apps without the need to provision or manage infrastructure. For more information, see
Amazon Lambda (http://aws.amazon.com/lambda/).
The Mobile SDK for iOS enables you to call Amazon Lambda functions from your iOS mobile apps, using
the lambdainvoker class. When invoked from the Mobile SDK, Amazon Lambda functions receive data
about the device and the end user identity through a client and identity context object, making it easy to
create rich, and personalized app experiences. To learn more about the data available within the client and
identity context, see Client Context (page 91) and Identity Context (page 92).
The Building a Mobile Backend Using AWS Lambda (page 20) document describes step-by-step
instructions for integrating the AWS Mobile SDK for iOS into your app.
To use the LambdaInvoker API, use the following import statement:
#import <AWSLambda/AWSLambda.h>
13.1 Invoking a Amazon Lambda Function
AWSLambdaInvoker provides a high-level abstraction for Amazon Lambda. When
invokeFunction/:JSONObject/: is invoked, the JSON object is serialized into JSON data and sent to the
Amazon Lambda service. Amazon Lambda returns a JSON encoded response that is deserialized into a
JSON object.
A valid JSON object must have the following properties:
• All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull.
• All dictionary keys are instances of NSString.
• Numbers are not NaN or infinity.
For example, it is an example of valid request:
89
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
AWSLambdaInvoker *lambdaInvoker = [AWSLambdaInvoker defaultLambdaInvoker];
[[lambdaInvoker invokeFunction:@"myFunction"
JSONObject:@{@"key1" : @"value1",
@"key2" : @2,
@"key3" : [NSNull null],
@"key4" : @[@1, @"2"],
@"isError" : @NO}] continueWithBlock:^id(AWSTask *task) {
// Handle response
return nil;
}];
On successful execution, task.result contains a JSON object. For instance, if myFunctions returns a
dictionary, you can cast the result to an NSDictionary as follows:
if (task.result) {
NSLog(@"Result: %@", task.result);
NSDictionary *JSONObject = task.result;
NSLog(@"result: %@", JSONObject[@"resultKey"]);
}
On failed Amazon Lambda service execution, task.error may contain an NSError with
AWSLambdaErrorDomain domain and the following error code:
• AWSLambdaErrorUnknown
• AWSLambdaErrorService
• AWSLambdaErrorResourceNotFound
• AWSLambdaErrorInvalidParameterValue
On failed function execution, task.error may contain an NSError with AWSLambdaInvokerErrorDomain
domain and the following error code:
• AWSLambdaInvokerErrorTypeUnknown
• AWSLambdaInvokerErrorTypeFunctionError
When AWSLambdaInvokerErrorTypeFunctionError error code is returned, error.userInfo may contain a
function error from your Amazon Lambda function with AWSLambdaInvokerFunctionErrorKey key.
Here is an example code snippet:
if (task.error) {
NSLog(@"Error: %@", task.error);
if ([task.error.domain isEqualToString:AWSLambdaInvokerErrorDomain]
&& task.error.code == AWSLambdaInvokerErrorTypeFunctionError) {
NSLog(@"Function error: %@", task.error.userInfo[AWSLambdaInvokerFunctionErrorKey])
}
}
if (task.exception) {
NSLog(@"Exception: %@", task.exception);
}
With everything put together, here is a complete code snippet:
90
Chapter 13. Execute Code On Demand with Amazon Lambda
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
AWSLambdaInvoker *lambdaInvoker = [AWSLambdaInvoker defaultLambdaInvoker];
[[lambdaInvoker invokeFunction:@"myFunction"
JSONObject:@{@"key1" : @"value1",
@"key2" : @2,
@"key3" : [NSNull null],
@"key4" : @[@1, @"2"],
@"isError" : @NO}] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"Error: %@", task.error);
if ([task.error.domain isEqualToString:AWSLambdaInvokerErrorDomain]
&& task.error.code == AWSLambdaInvokerErrorTypeFunctionError) {
NSLog(@"Function error: %@", task.error.userInfo[AWSLambdaInvokerFunctionErrorK
}
}
if (task.exception) {
NSLog(@"Exception: %@", task.exception);
}
if (task.result) {
NSLog(@"Result: %@", task.result);
NSDictionary *JSONObject = task.result;
NSLog(@"result: %@", JSONObject[@"resultKey"]);
}
return nil;
}];
13.2 Client Context
When invoked through the SDK, Amazon Lambda functions have access to the data about the device and
the app using thed ClientContext class. When you use Amazon Cognito as a credential provider, access to
the end user identity is available using the IdentityContext class.
You can access the client context in your lambda function as follows:
exports.handler = function(event, context) {
console.log("installation_id = " + context.clientContext.client.installation_id);
console.log("app_version_code = " + context.clientContext.client.app_version_code);
console.log("app_version_name = " + context.clientContext.client.app_version_name);
console.log("app_package_namae = " + context.clientContext.client.app_package_name);
console.log("app_title = " + context.clientContext.client.app_title);
console.log("platform_version = " + context.clientContext.env.platform_versioin);
console.log("platform = " + context.clientContext.env.platform);
console.log("make = " + context.clientContext.env.make);
console.log("model = " + context.clientContext.env.model);
console.log("locale = " + context.clientContext.env.locale);
context.succeed("Your platform is " + context.clientContext.env.platform;
}
ClientContext has the following fields:
13.2. Client Context
91
AWS Mobile SDK iOS Developer Guide, Release 0.0.3
client.installation_id Auto-generated UUID that is created the first time the app is launched. This is stored
in the keychain on the device. In case the keychain is wiped a new installation ID will be generated.
client.app_version_code CFBundleShortVersionString
(https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFound
111349)
client.app_version_name CFBundleVersion
(https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFound
102364)
client.app_package_name CFBundleIdentifier
(https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFound
102070)
client.app_title CFBundleDisplayName
(https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFound
110725)
env.platform_version systemVersion
(https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIDevice_Class/index.html#//apple_ref/occ/
env.platform systemName
(https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIDevice_Class/index.html#//apple_ref/occ/
env.make Hardcoded as “apple”
env.model Model of the device
(https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIDevice_Class/index.html#//apple_ref/occ/
env.locale localeIdentifier
(https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSLocale_Class/index.h
from autoupdatingCurrentLocale
(https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSLocale_Class/index.h
13.3 Identity Context
To invoke Amazon Lambda function from your mobile app, you can leverage Amazon Cognito as the
credential provider. You can learn more about Amazon Cognito here. Amazon Cognito assigns each user a
unique Identity ID. This Identity ID is available to you in the Amazon Lambda functions invoked through
the AWS Mobile SDK. You can access the Identity ID as follows:
exports.handler = function(event, context) {
console.log("clientID = " + context.identity);
context.succeed("Your client ID is " + context.identity);
}
For more information about Identity ID, see Amazon Cognito Identity
(http://docs.aws.amazon.com/mobile/sdkforandroid/developerguide/cognito-auth.html).
92
Chapter 13. Execute Code On Demand with Amazon Lambda
CHAPTER 14
Additional Resources
• For more information about the AWS SDK for iOS, including a complete list of supported AWS
products, see the AWS Mobile SDK product page (http://aws.amazon.com/mobile/sdk).
• The SDK reference documentation includes the ability to browse and search code included with the
SDK. It provides thorough documentation and usage examples. You can find it at AWS SDK for iOS
API Reference (http://docs.aws.amazon.com/AWSiOSSDK/latest/).
• Post questions and feedback at the Mobile Developer Forum
(https://forums.aws.amazon.com/forum.jspa?forumID=88).
• Source code and sample applications are available at AWS SDK for iOS repository
(https://github.com/aws/aws-sdk-ios-v2). Source code for Amazon Cognito is available at the
Amazon Cognito repository (https://github.com/aws/amazon-cognito-ios).
93
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertising