この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
Amplify iOS
Amplify iOSおよびAmplify Androidは、AWS re:Invent 2019で発表されたAmplify Frameworkの新しいツール・ライブラリです。現在はプレビュー版として提供されています。
本記事ではGetting Startedに沿ってiOSアプリを作ってみました。
サンプルコードをGitHubで公開しましたので、合わせてご確認いただけますと幸いです。
インストール
Xcodeプロジェクト、およびCocoaPodsはすでに作成・導入済みの前提で進みます。本記事では AmplifySample
という名前のXcodeプロジェクトを作成しました。
まずはXcodeプロジェクトのディレクトリを開き Podfile
を作成します。
$ cd ./AmplifySample
$ pod init
Podfile
は以下のようにします。
Podfile
target 'AmplifySample' do
use_frameworks!
# Pods for AmplifySample
pod 'amplify-tools'
pod 'Amplify'
pod 'AWSPluginsCore'
pod 'AmplifyPlugins/AWSAPIPlugin'
end
pod install
を実行し、各ライブラリをインストールします。
$ pod install --repo-update
Xcodeワークスペースが作成されます AmplifySample.xcworkspace
を開きビルドを行います。ビルドは Command + B で行えます。
ビルドすると下図のように3つの設定ファイルが生成されます。
それぞれ次のような設定が含まれるようになります。
awsconfiguration.json
とamplifyconfiguration.json
: AmplifyとしてAWSの各リソースを作る際の設定ファイルamplifyxc.config
: XcodeからAmplify Frameworkの操作を行う際の設定ファイル
モデルの作成
Amplify iOSでは、デフォルトでGraphQL (AppSync)と通信することでデータを取得したりする前提で各設定が行われています。
amplify/backend/api/amplifyDatasource/schema.graphql
にファイルが作成されており、確認してみると下記のようなGraphQLスキーマが作られています。
type Task @model {
id: ID!
title: String!
description: String
status: String
}
type Note @model {
id: ID!
content: String!
}
このGraphQL Schemaを元に、モデルクラスを作ってみます。モデルクラスを作る場合は amplifyxc.config
の設定を変更し modelgen=true
にします。
push=false
modelgen=true
profile=default
envName=amplify
ビルドすると次のファイルが amplify/generated/models
に生成されます。
AmplifyModels.swift
Note.swift
Note+Schema.swift
Task.swift
Task+Schema.swift
生成したファイルはXcode ProjectのTarget内に追加します。
最後にビルドしておきます。
APIとDatabaseの追加
push=true
modelgen=true
profile=default
envName=amplify
profile
は ~/.aws/config
に設定してあるProfileを利用することが可能です。しかしMFAには対応していないようなのでご留意ください。MFAが不要なIAM Userで実行可能です。
ビルドを実行するとAWSアカウント上に各種リソースが作成されます。awsconfiguration.json
と amplifyconfiguration.json
に設定が増えていることが確認できます。
awsconfiguration.json
{
"UserAgent": "aws-amplify/cli",
"Version": "0.1.0",
"IdentityManager": {
"Default": {}
},
"AppSync": {
"Default": {
"ApiUrl": "https://<api id>.appsync-api.ap-northeast-1.amazonaws.com/graphql",
"Region": "ap-northeast-1",
"AuthMode": "API_KEY",
"ApiKey": "<api key>",
"ClientDatabasePrefix": "amplifyDatasource_API_KEY"
}
}
}
amplifyconfiguration.json
{
"api": {
"plugins": {
"awsAPIPlugin": {
"amplifyDatasource": {
"endpointType": "GraphQL",
"endpoint": "https://<api id>.appsync-api.ap-northeast-1.amazonaws.com/graphql",
"region": "ap-northeast-1",
"authorizationType": "API_KEY",
"apiKey": "<api key>"
}
}
}
}
}
APIを利用したアプリの実装
ここまででAPIの用意ができたので、アプリにAPIを呼び出す処理を実装します。
AppDelegate での初期化
AppDelegate.swift
の application:didFinishLaunchingWithOptions:
メソッド内に次の処理を追加します。
AppDelegate.swift
import UIKit
import Amplify
import AmplifyPlugins
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let apiPlugin = AWSAPIPlugin(modelRegistration: AmplifyModels())
do {
try Amplify.add(plugin: apiPlugin)
try Amplify.configure()
print("Amplify initialized")
} catch {
print("Failed to configure Amplify \(error)")
}
return true
}
}
View Controllerで書き込み/読み込みを試す
次にView Controller内でAPIに対してのデータの書き込み/読み込みを試していきたいと思います。
まずView Controllerでデータの確認ができるよう、下図のようにViewを配置します。
続いてView Controllerの実装です。以下のように実装しました。
ViewController.swift
import UIKit
import Amplify
class ViewController: UIViewController {
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var tableView: UITableView!
var list = [Note]()
override func viewDidLoad() {
super.viewDidLoad()
query()
subscribe()
}
@IBAction func postButtonDidTouch(_ sender: Any) {
let content = textField.text ?? ""
let note = Note(content: content)
_ = Amplify.API.mutate(of: note, type: .create) { (event) in
switch event {
case .completed(let result):
switch result {
case .success(let note):
print("API Mutate successful, created note: \(note)")
DispatchQueue.main.async {
self.textField.text = nil
}
case .failure(let error):
print("Completed with error: \(error.errorDescription)")
}
case .failed(let error):
print("Failed with error \(error.errorDescription)")
default:
print("Unexpected event")
}
}
}
func query() {
_ = Amplify.API.query(from: Note.self, where: nil) { (event) in
switch event {
case .completed(let result):
switch result {
case .success(let notes):
print("Successfully retrieved list of notes: \(notes)")
self.list = notes
DispatchQueue.main.async {
self.tableView.reloadData()
}
case .failure(let error):
print("Got failed result with \(error.errorDescription)")
}
case .failed(let error):
print("Got failed event with error \(error)")
default:
print("Should never happen")
}
}
}
func subscribe() {
_ = Amplify.API.subscribe(from: Note.self, type: .onCreate) { (event) in
switch event {
case .inProcess(let subscriptionEvent):
switch subscriptionEvent {
case .connection(let subscriptionConnectionState):
print("Subsription connect state is \(subscriptionConnectionState)")
case .data(let result):
switch result {
case .success(let note):
print("Successfully got todo from subscription: \(note)")
self.list.append(note)
DispatchQueue.main.async {
self.tableView.reloadData()
}
case .failure(let error):
print("Got failed result with \(error.errorDescription)")
}
}
case .completed:
print("Subscription has been closed")
case .failed(let error):
print("Got failed result with \(error.errorDescription)")
default:
print("Should never happen")
}
}
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return list.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
let note = list[indexPath.row]
cell.textLabel?.text = note.content
return cell
}
}
上記の実装コードのポイントは下記の通りです。
- View Controllerが表示された際にSubscribeを開始
- TextInputに入力し、Buttonで投稿をしたらAPIにリクエスト
- 新しいデータが作成されたらSubscribeイベントが到着
- 新しいデータをTableViewに反映
以上で完了です。
動かす
それではiOSアプリとして動かしてみます。Command + R でデバッグ起動します。何かしらを書き込んでみます。投稿するとクラウド上にデータが保存され、TableViewにアイテムが追加されます。
バックエンド側を簡単に確認してみます。CloudFormationを見てもらうと分かりますが、Amplify経由でAppSyncやDynamoDB、Cognito User Poolといったリソースが作成されています。
DynamoDBのNoteテーブルを確認してみると、先ほど追加したデータが格納されていることが分かります。
コマンドラインでの操作不要でAmplify Frameworkが使える!
Amplify FrameworkではAmplify CLIをコマンドラインで実行しなければAPIの作成などは行えませんでした。今回のAmplify iOSおよびAmplify AndroidではXcodeなどの統合開発環境(IDE)からAmplify Frameworkの操作が行えます。これはモバイルアプリ開発者にとっては非常に嬉しい限りですね!
他にもPredictionsなどの面白い機能があるので、試していきたいと思います。