Get started with the AWS SDK for Swift - AWS SDK for Swift

Get started with the AWS SDK for Swift

This chapter explores how to use the Swift Package Manager — part of the standard Swift toolchain — to create and build a small project. The project uses the AWS SDK for Swift to output a list of available Amazon Simple Storage Service (Amazon S3) buckets.

Create a project using the AWS SDK for Swift

This chapter demonstrates how to create a small program that lists all the Amazon S3 buckets available on the default user account.

Goals for this project:

  • Create a project using Swift Package Manager.

  • Add the AWS SDK for Swift to the project.

  • Configure the project’s Package.swift file to describe the project and its dependencies.

  • Write code that uses Amazon S3 to get a list of the buckets on the default AWS account, then prints them to the screen.

Before we begin, make sure to prepare your development environment as described in Set up. To make sure you're set up properly, use the following command. This makes sure that Swift is available and which version it is.

$ swift --version

On macOS, you should see output that looks like the following (with possibly different version and build numbers):

swift-driver version: 1.87.1 Apple Swift version 5.9 (swiftlang-5.9.0.128.108 clang-1500.0.40.1)
Target: x86_64-apple-macosx14.0

On Linux, the output should look something like the following:

Swift version 5.9.0 (swift-5.9.0-RELEASE)
Target: x86_64-unknown-linux-gnu

If Swift is not installed, or is older than version 5.9, follow the instructions in Set up the AWS SDK for Swift to install or reinstall the tools.

Get this example on GitHub

You can fork or download this example from the AWS SDK for Swift code examples repository.

Create the project

With the Swift tools installed, open a terminal session using your favorite terminal application (such as Terminal, iTerm, or the integrated terminal in your editor).

At the terminal prompt, go to the directory where you want to create the project. Then, enter the following series of commands to create an empty Swift project for a standard executable program.

$ mkdir ListBuckets $ cd ListBuckets $ swift package init --type executable $ mv Sources/main.swift Sources/entry.swift

This creates the directory for the examples project, moves into that directory, and initializes that directory with the Swift Package Manager. The result is the basic file system structure for a simple executable program. The Swift source code file main.swift is also renamed to entry.swift to work around a bug in the Swift tools that involves the use of asynchronous code in the main function of a source file named main.swift.

ListBuckets/
├── Package.swift
└── Sources/
   └── entry.swift

Open your created project in your preferred text editor or IDE. On macOS, you can open the project in Xcode with the following:

$ xed .

As another example, you can open the project in Visual Studio Code with the following:

$ code .

Configure the package

After opening the project in your editor, open the Package.swift file. This is a Swift file that defines an SPM Package object that describes the project, its dependencies, and its build rules.

The first line of every Package.swift file must be a comment specifying the minimum version of the Swift toolchain needed to build the project. This isn't only informational. The version specified here can change the behavior of the tools for compatibility purposes. The AWS SDK for Swift requires at least version 5.9 of the Swift tools.

// swift-tools-version:5.9

Specify supported platforms

For projects whose target operating systems include any Apple platform, add or update the platforms property to include a list of the supported Apple platforms and minimum required versions. This list only specifies support for Apple platforms and doesn't preclude building for other platforms.

// Let Xcode know the minimum Apple platforms supported. platforms: [ .macOS(.v11), .iOS(.v13) ],

In this excerpt, the supported Apple platforms are macOS (version 11.0 and higher) and iOS/iPadOS (version 13 and higher).

Set up dependencies

The package dependency list needs to include the AWS SDK for Swift. This tells the Swift compiler to fetch the SDK and its dependencies before attempting to build the project.

dependencies: [ // Dependencies declare other packages that this package depends on. .package( url: "https://github.com/awslabs/aws-sdk-swift", from: "1.0.0" ) ],

Configure the target

Now that the package depends on the AWS SDK for Swift, add a dependency to the executable program's target. Indicate that it relies on the Amazon S3 module, which is offered by the SDK's AWSS3 product.

targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. // Targets can depend on other targets in this package and products from dependencies. .executableTarget( name: "ListBuckets-Simple", dependencies: [ .product(name: "AWSS3", package: "aws-sdk-swift") ], path: "Sources") ]

Access AWS services using Swift

The example program's Swift code is found in the Source/entry.swift file. This file begins by importing the needed Swift modules, using the import statement.

import AWSClientRuntime import AWSS3 import Foundation
  • Foundation is the standard Apple Foundation package.

  • AWSS3 is the SDK module that's used to access Amazon S3.

  • AWSClientRuntime contains runtime components used by the SDK.

After you add the SDK for Swift to your project and import the service you want to use into your source code, you can create an instance of the client representing the service and use it to issue AWS service requests.

Create a service client object

Each AWS service is represented by a specific client class in the AWS SDK for Swift. For example, while the Amazon DynamoDB client class is called DynamoDBClient, the class for Amazon Simple Storage Service is S3Client. To use Amazon S3 in this example, first create an S3Client object on which to call the SDK's Amazon S3 functions.

let configuration = try await S3Client.S3ClientConfiguration() // configuration.region = "us-east-2" // Uncomment this to set the region programmatically. let client = S3Client(config: configuration)

Issue AWS service requests

To issue a request to an AWS service, call the corresponding function on the service's client object. Each function's inputs are specified using a function-specific input structure as the value of the function's input parameter. For example, when calling S3Client.listBucketsPaginated(input:), input is a structure of type ListBucketsInput.

// Use "Paginated" to get all the buckets. // This lets the SDK handle the 'continuationToken' in "ListBucketsOutput". let pages = client.listBucketsPaginated( input: ListBucketsInput( maxBuckets: 10) )

This function receives batches of results until all available buckets have been returned. If SDK functions encounter errors, they are thrown by the SDK so your code can handle them using a do-catch statement or by propagating them back to the caller.

Most SDK functions are asynchronous, and should be called with the await keyword to wait for the response to arrive before continuing with execution. listBucketsPaginated(input:) happens to be an exception. Its results need to be accessed using await.

Get all bucket names

This example's main program calls getBucketNames() to get an array containing all of the bucket names. That function is defined as follows.

// Return an array containing the names of all available buckets. // // - Returns: An array of strings listing the buckets. func getBucketNames() async throws -> [String] { do { // Get an S3Client with which to access Amazon S3. let configuration = try await S3Client.S3ClientConfiguration() // configuration.region = "us-east-2" // Uncomment this to set the region programmatically. let client = S3Client(config: configuration) // Use "Paginated" to get all the buckets. // This lets the SDK handle the 'continuationToken' in "ListBucketsOutput". let pages = client.listBucketsPaginated( input: ListBucketsInput( maxBuckets: 10) ) // Get the bucket names. var bucketNames: [String] = [] do { for try await page in pages { guard let buckets = page.buckets else { print("Error: no buckets returned.") continue } for bucket in buckets { bucketNames.append(bucket.name ?? "<unknown>") } } return bucketNames } catch { print("ERROR: listBuckets:", dump(error)) throw error } } }

This function starts by creating an Amazon S3 client and calling its listBucketsPaginated(input:) function to request a list of all of the available buckets. The resulting buckets are added to an asynchronous variable, pages, and are processed using a for loop and the await keyword.. For each bucket returned, the bucket's name is fetched from the output structure's buckets property. If the buckets property is nil, the current array of found bucket names, bucketNames, is immediately returned to the caller. Otherwise, each bucket name is added to the array.

By the time the do-catch block ends (as long as it doesn't end in an error being thrown), the bucketNames array contains the names of every bucket available to the user.

Add the example entry point

To allow the use of asynchronous functions from within main(), use Swift's @main attribute to create an object that contains a static async function called main(). Swift will use this as the program entry point.

/// The program's asynchronous entry point. @main struct Main { static func main() async { do { let names = try await getBucketNames() print("Found \(names.count) buckets:") for name in names { print(" \(name)") } } catch let error as AWSServiceError { print("An Amazon S3 service error occurred: \(error.message ?? "No details available")") } catch { print("An unknown error occurred: \(dump(error))") } } }

main() calls getBucketNames(), then outputs the returned list of names. Errors thrown by getBucketNames() are caught and handled. Errors of type AWServiceError, which represent errors reported by an AWS service, are handled specially.

Add the AWS SDK for Swift to an existing Xcode project

If you have an existing Xcode project, you can add the SDK for Swift to it. Open your project's main configuration pane and choose the Package Dependencies tab at the right end of the tab bar. The following image shows this tab for an Xcode project called "Supergame," which will use Amazon S3 to get game data from a server.

The Package Dependencies tab lists the Swift packages currently in use by your project. If you haven't added any Swift packages, the list will be empty, as shown in the preceding image. To add the SDK to your project, choose the + button under the package list. This brings up a panel for finding and adding packages to your project. You can find the AWS SDK for Swift by typing aws-sdk-swift in the search box. You can also paste the URL of the GitHub project for the SDK, https://github.com/awslabs/aws-sdk-swift.git, into the search box.

You can also configure version requirements and other options for the SDK package import. By default, the minimum version is the current version of the SDK, and the maximum is anything before the next major version number. After confirming these settings are satisfactory, click the Add Package button. While the package and its dependencies are downloaded and added to your project, a panel containing progress information will be displayed:

Once the SDK and its dependencies have been retrieved, a panel appears to let you select specific products (or modules) from the AWS SDK for Swift package to include in your project. Each product generally corresponds to one AWS service. Each package is listed by package name, starting with AWS and followed by the shorthand name of the service or toolkit.

For the Supergame project, select AWSS3, AWSDynamoDB, and AWSGameLift. Assign them to the correct target (macOS in this example, but the principle is the same for iOS), and choose Add Package. The image below shows this panel with the AWSS3 module added to the Supergame application target.

Your project is now configured to import the AWS SDK for Swift package and to include the desired service modules in the build for that target. To see a list of the AWS SDK for Swift modules that are available for import, open the target's General tab and scroll down to Frameworks, Libraries, and Embedded Content.

If your project is multi-platform, you also need to add the AWS libraries to the other targets in your project. If you didn't do that when first adding the modules to your project, you can do so in each platform's target pane. Navigate to the Frameworks, Libraries, and Embedded Content section under the General tab and choose + to open the library picker window.

Then, you can scroll to find and select all of the needed modules or products and choose Add to add them all at once. Alternatively, you can search for and select each product or module, then choose Add to add them to the target one at a time.

You're now ready to import the modules and any needed dependencies into individual Swift source code files and start using the AWS services in your project. Build your project by using the Xcode Build option in the Product menu.

Build and run an SPM project

To build and run a Swift project from a Linux or macOS terminal prompt, use the following commands.

Build a project

$ swift build

Run a project

$ swift run $ swift run executable-name $ swift run executable-name arg1, ...

If your project builds only one executable file, you can type swift run to build and run it. If your project outputs multiple executables, you can specify the file name of the executable you want to run. If you want to pass command-line arguments to the program when you run it, you must specify the executable name before listing the arguments.

Get the built product output directory

$ swift build --show-bin-path /home/janice/MyProject/.build/x86_64-unknown-linux-gnu/debug

Delete build artifacts

$ swift package clean

Delete build artifacts and all build caches

$ swift package reset

Import AWS SDK for Swift libraries into source files

After the libraries are in place, you can use the Swift import directive to import the individual libraries into each source file that needs them. To use the functions for a given service, import its module from the AWS SDK for Swift package into your source code file. Also import the AWSClientRuntime library, which contains utility functions and type definitions. It's not always needed but is used often enough to be worth importing by default until you're more familiar with the SDK.

import Foundation import AWSClientRuntime import AWSS3

The standard Swift library Foundation is also imported because it's used by many features of the AWS SDK for Swift.

Additional information