こんにちは、AWS事業本部の荒平(@0Air)です。
Swift(iOS)でAWSの各リソースを触ってみたいなと思うことはありませんか?私は年10回くらい思います。
私はSwiftは2.xの頃に少し触れただけのズブの素人なので、今は何もかも変わってしまっていますが、いい感じのGet Startedがあったので試しに触ってみたいと思います。
以下のドキュメントに沿って確認してみます。
はじめに
- 執筆時点で、上記ドキュメントはプレビューリリースです。記載する全ての内容は変更される場合があります
- 実稼働での利用は推奨されていません
- 筆者環境は、
Apple Swift version 5.9.2 (swiftlang-5.9.2.2.56 clang-1500.1.0.2.5)
および、aws-sdk-swift v0.36.1
にて試しました - 最小バージョンの要件は
Swift 5.7
およびXcode 14
です。
プロジェクトの作成
ドキュメントに従い、以下コマンドにてプロジェクトを作成します。
mkdir ListBuckets
cd ListBuckets
swift package init --type executable
mv Sources/main.swift Sources/entry.swift
ファイル構成は以下のようになります。
$ tree
.
├── Package.swift
└── Sources
└── entry.swift
Package.swift
およびentry.swift
はgitにて公開されていますので、そちらからコピーしてもよいと思います。(参考)
Package.swift
は以下のように記述しました。
特に15行目は、ご利用の環境に合わせてバージョンを変更してください。
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "ListBuckets",
platforms: [
.macOS(.v11),
.iOS(.v13)
],
dependencies: [
.package(
url: "https://github.com/awslabs/aws-sdk-swift",
from: "0.36.1"
)
],
targets: [
.executableTarget(
name: "ListBuckets-Simple",
dependencies: [
.product(name: "AWSS3", package: "aws-sdk-swift")
],
path: "Sources")
]
)
entry.swift
は以下の通りです。
9行目region:
は確認したいリージョンに変更します。
// The Swift Programming Language
// https://docs.swift.org/swift-book
import Foundation
import ClientRuntime
import AWSS3
func getBucketNames() async throws -> [String] {
let client = try S3Client(region: "ap-northeast-1")
let output = try await client.listBuckets(
input: ListBucketsInput()
)
var bucketNames: [String] = []
guard let buckets = output.buckets else {
return bucketNames
}
for bucket in buckets {
bucketNames.append(bucket.name ?? "<unknown>")
}
return bucketNames
}
@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 ServiceError {
print("An Amazon S3 service error occurred: \(error.message ?? "No details available")")
} catch {
print("An unknown error occurred: \(dump(error))")
}
}
}
サンプルコードを実行してみる
それぞれファイルを変更して保存したら、ターミナルからswift build
にてビルドします。
$ swift build
Building for debugging...
[3/3] Linking ListBuckets-Simple
Build complete! (3.46s)
swift run
にてコードを実行できますが、この際、ターミナルの認証情報を利用するため注意が必要です。
~/.aws/credentials
に認証情報をセットしていない場合は、一時的に以下のコマンドで設定します。
export AWS_ACCESS_KEY_ID="YOUR_ACCESS_KEY_ID"
export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_ACCESS_KEY"
そして実行すると、しっかりS3バケットの一覧が取得できました。
$swift run
Building for debugging...
Build complete! (0.25s)
2024-02-24T02:49:54+0900 info S3Client : [Logging] Request: GET https:443
Path: /
User-Agent: aws-sdk-swift/1.0 ua/2.0 api/s3#1.0 os/macos#14.2.1 lang/swift#5.9 cfg/retry-mode#legacy,
X-Amz-Date: 20240223T174954Z,
Host: s3.ap-northeast-1.amazonaws.com,
x-amz-content-sha256: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
Authorization: AWS4-HMAC-SHA256 Credential=AKIAXXXXXXXXXXXXXXXX/20240223/ap-northeast-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Optional([ClientRuntime.SDKURLQueryItem(name: "x-id", value: Optional("ListBuckets"))])
2024-02-24T02:49:55+0900 info URLSessionHTTPClient : [Logging] urlSession(_:dataTask:didReceive:) called
2024-02-24T02:49:55+0900 info URLSessionHTTPClient : [Logging] urlSession(_:dataTask:didReceive:) called with 1936 bytes
2024-02-24T02:49:55+0900 info URLSessionHTTPClient : [Logging] urlSession(_:task:didCompleteWithError:) called. Success
Found 15 buckets:
amazon-connect-xxxxxxx
aws-glue-assets-xxxxxxx-ap-northeast-1
backup-data-arap
(省略)
(参考)既存プロジェクトに対して導入する場合
既存のプロジェクトに対してAWS SDK for Swift
パッケージをプロジェクトに追加します。
`https://github.com/awslabs/aws-sdk-swift` を検索欄に入力し、 "Add to Project"にて追加先のプロジェクトを指定、 "Add Package"にてパッケージをインポートします。
AWS SDK for Swiftのインポートが始まります。
少し待機するとサービス一覧が表示されるので、利用するサービス(例えば、AWSS3
)をプロジェクトに追加指定します。
チュートリアルはここまで
・・・なのですが、やはりiOSの画面でも表示させたいなぁと思ったので、作ってみました。
コード例
以下、作成したサンプルコードです。3ファイルに分割しています。
Main.swift
import Foundation
import ClientRuntime
import AWSS3
import SwiftUI
func getBucketNames() async throws -> [String] {
let client = try S3Client(region: "ap-northeast-1")
let output = try await client.listBuckets(
input: ListBucketsInput()
)
var bucketNames: [String] = []
guard let buckets = output.buckets else {
return bucketNames
}
for bucket in buckets {
bucketNames.append(bucket.name ?? "<unknown>")
}
return bucketNames
}
@main
struct awssdkforswift: App {
var body: some Scene {
WindowGroup {
BucketListView()
}
}
}
BucketListView.swift
import SwiftUI
struct BucketListView: View {
@StateObject private var viewModel = BucketListViewModel()
var body: some View {
NavigationView {
List(viewModel.bucketNames, id: \.self) { name in
Text(name)
}
.navigationTitle("S3 Buckets")
.onAppear {
viewModel.fetchBucketNames()
}
}
}
}
BucketListViewModel.swift
import SwiftUI
import Combine
class BucketListViewModel: ObservableObject {
@Published var bucketNames: [String] = []
@Published var isLoading = false
@Published var errorMessage: String?
func fetchBucketNames() {
isLoading = true
Task {
do {
let names = try await getBucketNames()
DispatchQueue.main.async {
self.bucketNames = names
self.isLoading = false
}
} catch {
DispatchQueue.main.async {
self.errorMessage = error.localizedDescription
self.isLoading = false
}
}
}
}
}
最後に、適当なXcodeプロジェクトを新規作成し、作成したコードをプロジェクトにAddします。
(デバイスは、特にこだわりはありませんが、iPhone 15 Proを指定しました)
認証情報の設定
iOSで表示させるためには、XcodeにAWS操作用の認証情報を設定してあげる必要があります。
※ ここでは、検証のために環境変数で設定しますが、プロダクションでは非推奨です
Scheme
> Edit Scheme
から、スキーマ操作画面に移動します。
Run
の環境変数を設定します。設定するのは以下の3変数です。
- AWS_REGION
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
S3バケットの一覧が表示できた!
実行してみると、アプリ上からAmazon S3のバケット一覧を取得することができました。
辿り着くまで紆余曲折あったのですが、Xcodeはエラーメッセージが優しい(諸説あり)ので、なんとかなりました。
おわりに
実施内容は基本的ですが、AWS SDK for Swift
を利用すると色々できそうなことが分かりました。
今回は環境変数にアクセスキーを直で入れましたが、本来は別の認証方法を利用すべきなので、要改善です。
2021年終盤に登場し、まだプレビューリリースではありますが、直近でもかなり活発にコミットされていそうなので、幅広く遊べそうです。
このエントリが誰かの助けになれば幸いです。
それでは、AWS事業本部 コンサルティング部の荒平(@0Air)がお送りしました!