こんにちは。きんくまです。
前回設定したAPIはブラウザのJSからアクセスしました。
>> [AWS] API Gateway で Authorization AWS_IAM のときに JavaScript SDKからアクセスする
今回はiOSからつなぎたいと思います。
いくつかはまりどころがあったので、それのメモみたいな感じです。
CocoaPodsでライブラリをインストール
CocoaPodsでライブラリをインストールします。
公式のチュートリアルだとそれと合わせてAWS Amplify CLIを入れてねとなっていました。
Amplify CLIを少しやってみたところ、これはコマンドラインで複数のAWSのサービスを操作して、目的のバックエンドを作成するやつでした。これを使うことでAWSにそこまで詳しくなくてもユーザー認証とかプッシュ通知とかすぐにできる感じのようです。Google Firebaseの対抗ということでしょうかね?ページのデザインも似てますし。
>> AWS Amplify
今回は特にサーバー側をCLIからは操作しないので、入れません。
でCocoaPodsで入れるライブラリとしては、AWSのベースとなるAWSCoreと、API Gateway用のAWSAPIGatewayとなります。
Podfile
# platform :ios, '9.0' target 'SamplePod' do use_frameworks! pod 'AWSCore', '~> 2.6.13' pod 'AWSAPIGateway', '~> 2.6.13' end
バージョンについて。あとから出てくるAPI Gatewayで書き出されたPodfileにはもっと低いバージョンの2.5.3が書いてあったのですが、それでやったらいろいろとうまくいかなかったので新しいバージョンにしています。(2018/10月時点)
インストール
pod install
Lambdaのソース
前回特に書かなかったのですが、今回は出力の部分があるのでLambdaのソースを載せておきます。
基本チュートリアル通りなのですが、おまけで2桁の数字をランダムで作って lucky というプロパティで返しています。
'use strict'; var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; var times = ['morning', 'afternoon', 'evening', 'night', 'day']; console.log('Loading function'); exports.handler = function(event, context, callback){ let name = event.name === undefined ? 'you' : event.name; let city = event.city === undefined ? 'World' : event.city; let time = times.indexOf(event.time) < 0 ? 'day' : event.time; let day = days.indexOf(event.day) < 0 ? null : event.day; let greeting = 'Good ' + time + ', ' + name + ' of ' + city + '. '; if(day){ greeting += 'Happy ' + day + '!'; } console.log('Hello: ', greeting); let num = Math.floor(Math.random() * 100); let luckyStr = 'lucky num is ' + num; callback(null, { 'greeting': greeting, 'lucky': luckyStr }) };
API Gatewayのモデルを作る
レスポンスされるときにモデルを作っておかないと、zipで吐き出されるソースでうまくいかなかったので先に出力モデルを作ります。ここはJSでは必要ないところでした。
GetStartedLamdaIntegrationResult
{ "$schema": "http://json-schema.org/draft-04/schema#", "title": "GetStartedLamdaIntegrationResultModel", "type": "object", "properties": { "greeting": { "type": "string" }, "lucky": {"type": "string"} } }
さきほどLambdaで返した greeting と lucky が入っています。
レスポンスに設定する
さきほどのモデルをPOSTのレスポンスに設定します。デフォルトではEmptyというふうになっていました。
ソースをダウンロード
ソースをダウンロードしてXcodeのプロジェクトに追加しておきます。
ソースを入れたら、チュートリアルにあるようにBridging-headerを設定します。SwiftからObjective-Cを利用できるようになりました。
で、ここでハマったところだったのですが、AWSModelの子供クラスは全て @objcMembers というのをつけてあげないとうまくいきませんでした。
>> API Gateway iOS SDK empty body?
今回だとこんな感じになりました。吐き出されたソースにあったAWSModelの子供クラスは Empty, SPGetStartedLambdaIntegrationUserInput, SPGetStartedLamdaIntegrationResultがありました。
@objcMembers public class SPGetStartedLambdaIntegrationUserInput : AWSModel {
swiftから利用してみる
ようやく準備が整いました。swiftからリクエストしてみます。
前回ハマったので今回は大丈夫だったのですが、Cognitoで認証してからリクエストしました。
import UIKit import AWSCore class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let credentialsProvider = AWSCognitoCredentialsProvider( regionType: AWSRegionType.APNortheast1, identityPoolId: "ap-northeast-1:XXXXXXXXX") let configuration = AWSServiceConfiguration( region: AWSRegionType.APNortheast1, credentialsProvider: credentialsProvider) AWSServiceManager.default()?.defaultServiceConfiguration = configuration if credentialsProvider.identityId == nil { // print("id not found") credentialsProvider.getIdentityId().continueWith { [weak self](task) -> Any? in guard task.error != nil else { print("Error: " + task.error!.localizedDescription) return task } // let cognitoId = task.result! // print("result: \(cognitoId)") // if let id = credentialsProvider.identityId { // print("ispopulate? -> \(id)") // } self?.testPost() return task } }else{ testPost() } } func testPost(){ let client = SPGetStartedLambdaIntegrationAPIClient.default() guard let model = SPGetStartedLambdaIntegrationUserInput() else { return } model.callerName = "Mike" client.cityPost(day: "Tuesday", time: "afternoon", city: "Hokaido", body: model) .continueWith { (task) -> Any? in //print("task \(task)") self.showResult(task: task) return nil } } func showResult(task:AWSTask<SPGetStartedLamdaIntegrationResult>){ if let error = task.error { print("Error: \(error)") return } guard let result = task.result else { return } if let greeting = result.greeting { print("greeting: \(greeting)") } if let lucky = result.lucky { print("lucky: \(lucky)") } } }
出力
greeting: Good afternoon, Mike of Hokaido. Happy Tuesday! lucky: lucky num is 51
うまくいきました! 前回ハマってしまった認証のところがわかっていたので、比較的スムーズにできました。
ところどころハマるところがあってググる必要があるのですが、基本的にAWSのドキュメントを順番に読んでいけば詳しく書いてあるので、なんとかなるのではないかと思いました。ではでは。
■ 自作iPhoneアプリ 好評発売中!
・フォルメモ - シンプルなフォルダつきメモ帳
・ジッピー電卓 - 消費税や割引もサクサク計算!
■ LINEスタンプ作りました!
毎日使える。とぼけたウサギ