AWS Mobile
Developer Guide

iOS: Execute Code On Demand with AWS Lambda

Just Getting Started?

Use streamlined steps to install the SDK and integrate AWS Lambda functions. Use the contents of this page if your app will integrate existing AWS services.

Overview

The AWS Lambda service makes it easy to create scalable, secure, and highly available backends for your mobile apps without the need to provision or manage infrastructure.

You can create secure logical functions in the cloud that can be called directly from your iOS app. Your AWS Lambda code, written in C#, Node.js, Python, or Java, can implement standalone logic, extend your app to a range of AWS services, and/or connect to services and applications external to AWS.

The availability and cost of a AWS Lambda function automatically scales to amount of traffic it receives. Functions can also be accessed from an iOS app through Amazon API Gateway, giving features like global provisioning, enterprise grade monitoring, throttling and control of access.

Setup

This section provides a step-by-step guide for getting started with AWS Lambda using the AWS Mobile SDK for iOS.

  1. Install the SDK

    Add the AWS SDK for iOS to your project and import the APIs you need, by following the steps described in Set Up the AWS SDK for iOS.

  2. Configure Credentials

    To use Amazon Cognito to create AWS identities and credentials that give your users access to your app's AWS resources, follow the steps described in Add User Sign-in.

  3. Create and Configure a Lambda Function

    1. Sign in to the AWS Lambda console.

    2. Choose Create a Lambda function.

    3. Choose the Blank Function template.

      Note that dozens of function templates that connect to other AWS services are available.

    4. Choose Next.

      Note that the console allows you to configure triggers for a function from other AWS services, these won't be used in this walkthrough.

    5. Type a Name and select Node.js as the Runtime language.

    6. Under Lambda function handler and role, select Create new role from template(s). Type a Role name. Select the Policy template named Simple Microservice permissions.

    7. Choose Next.

    8. Choose Create function.

Invoking an AWS Lambda Function

The SDK enables you to call AWS Lambda functions from your iOS mobile apps, using the AWSLambdaInvoker class. When invoked from this SDK, AWS Lambda functions receive data about the device and the end user identity through client and identity context objects. To learn more about using these contexts to create rich, and personalized app experiences, see Client Context and Identity Context.

Import AWS Lambda API

To use the lambdainvoker API, use the following import statement:

iOS - SwiftObjective C
iOS - Swift
import AWSLambda
Objective C
#import <AWSLambda/AWSLambda.h>

Call lambdaInvoker

AWSLambdaInvoker provides a high-level abstraction for AWS Lambda. When invokeFunction JSONObject is invoked, the JSON object is serialized into JSON data and sent to the AWS Lambda service. AWS 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 string, number, array, dictionary or null objects.

  • All dictionary keys are instances of string objects.

  • Numbers are not NaN or infinity.

The following is an example of valid request.

iOS - SwiftObjective C
iOS - Swift
let lambdaInvoker = AWSLambdaInvoker.default() let jsonObject: [String: Any] = ["key1" : "value1", "key2" : 2 , "key3" : [1, 2], "isError" : false] lambdaInvoker.invokeFunction("myFunction", jsonObject: jsonObject) .continueWith(block: {(task:AWSTask<AnyObject>) -> Any? in if( task.error != nil) { print("Error: \(task.error!)") return nil } // Handle response in task.result return nil })
Objective C
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; }];

Using function returns

On successful execution, task.result contains a JSON object. For instance, if myFunctions returns a dictionary, you can cast the result to a dictionary object as follows.

iOS - SwiftObjective C
iOS - Swift
if let JSONDictionary = task.result as? NSDictionary { print("Result: \(JSONDictionary)") print("resultKey: \(JSONDictionary["resultKey"])") }
Objective C
if (task.result) { NSLog(@"Result: %@", task.result); NSDictionary *JSONObject = task.result; NSLog(@"result: %@", JSONObject[@"resultKey"]); }

Handling service execution errors

On failed AWS Lambda service execution, task.error may contain a NSError with AWSLambdaErrorDomain domain and the following error code.

  • AWSLambdaErrorUnknown

  • AWSLambdaErrorService

  • AWSLambdaErrorResourceNotFound

  • AWSLambdaErrorInvalidParameterValue

On failed function execution, task.error may contain a 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 AWS Lambda function with AWSLambdaInvokerFunctionErrorKey key.

The following code shows error handling.

iOS - SwiftObjective C
iOS - Swift
if let error = task.error as? NSError { if (error.domain == AWSLambdaInvokerErrorDomain) && (AWSLambdaInvokerErrorType.functionError == AWSLambdaInvokerErrorType(rawValue: error.code)) { print("Function error: \(error.userInfo[AWSLambdaInvokerFunctionErrorKey])") } else { print("Error: \(error)") } return nil }
Objective C
if (task.error) { NSLog(@"Error: %@", task.error); if ([task.error.domain isEqualToString:AWSLambdaInvokerErrorDomain] && task.error.code == AWSLambdaInvokerErrorTypeFunctionError) { NSLog(@"Function error: %@", task.error.userInfo[AWSLambdaInvokerFunctionErrorKey]); } }

Comprehensive example

The following code shows invoking an AWS Lambda call and handling returns and errors all together.

iOS - SwiftObjective C
iOS - Swift
let lambdaInvoker = AWSLambdaInvoker.default() let jsonObject: [String: Any] = ["key1" : "value1", "key2" : 2, "key3" : [1, 2], "isError" : false] lambdaInvoker.invokeFunction("myFunction", jsonObject: jsonObject).continueWith(block: {(task:AWSTask<AnyObject>) -> Any? in if let error = task.error as? NSError { if (error.domain == AWSLambdaInvokerErrorDomain) && (AWSLambdaInvokerErrorType.functionError == AWSLambdaInvokerErrorType(rawValue: error.code) { print("Function error: \(error.userInfo[AWSLambdaInvokerFunctionErrorKey])") } else { print("Error: \(error)") } return nil } // Handle response in task.result if let JSONDictionary = task.result as? NSDictionary { print("Result: \(JSONDictionary)") print("resultKey: \(JSONDictionary["resultKey"])") } return nil })
Objective C
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[AWSLambdaInvokerFunctionErrorKey]); } } if (task.result) { NSLog(@"Result: %@", task.result); NSDictionary *JSONObject = task.result; NSLog(@"result: %@", JSONObject[@"resultKey"]); } return nil; }];

Client Context

Calls to AWS Lambda using this SDK provide your functions with data about the calling device and app using the ClientContext class.

You can access the client context in your lambda function as follows.

JavaScript
JavaScript
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_name = " + context.clientContext.client.app_package_name); console.log("app_title = " + context.clientContext.client.app_title); console.log("platform_version = " + context.clientContext.env.platform_version); 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:

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

client.app_version_name

CFBundleVersion

client.app_package_name

CFBundleIdentifier

client.app_title

CFBundleDisplayName

env.platform_version

systemVersion

env.platform

systemName

env.make

Hardcoded as "apple"

env.model

Model of the device

env.locale

localeIdentifier from autoupdatingCurrentLocale

Identity Context

The IdentityContext class of the SDK passes Amazon Cognito credentials making the AWS identity of the end user available to your function. You can access the Identity ID as follows.

JavaScript
JavaScript
exports.handler = function(event, context) { console.log("clientID = " + context.identity); context.succeed("Your client ID is " + context.identity); }