はじめに
AWS Mobile SDKを使えば、S3やDynamoDBといったAWSサービスをアプリで直接利用できるようになります。これはとても便利なことなのですが、実際にコーディングする時、オンラインのドキュメントだけでは使い方がなかなか分かりにくかったので、ソースコードを読んで理解を深めた話です。
この記事ではサービスクライアントの初期化について書いています。
なお、AWS Mobile SDK for iOSのバージョンはv2.4.14
で動作確認をしています。
各AWSサービスのサービスクライアントの初期化と取得には、いくつかの方法がありますが、基本的にはAWSServiceConfiguration
とサービス固有のコンフィギュレーションをセットして利用します。
例えば、DynamoDBを操作するAWSDynamoDBObjectMapper
ならばサービス固有のコンフィギュレーションとしてAWSDynamoDBObjectMapperConfiguration
が必要です。
また、サービス固有コンフィギュレーションは不要なクライアントもあります。
ちなみに、"サービス固有コンフィギュレーション"とは公式な呼び方ではなく、僕が勝手にそう呼んでいるだけです。
サービスコンフィギュレーションの設定方法
AWSServiceConfiguration
をサービスクライアントに設定する方法は以下の3通りがあります。
- Info.plistに記述する
-
[AWSServiceManager defaultServiceManager].defaultServiceConfiguration
にセットする -
registerXxxxWithConfiguration:XxxxConfiguration:forKey:
メソッドを使って設定する
1. Info.plistに記述する
1.の方法では、Info.plistに以下を記述します。
<key>AWS</key>
<dict>
<key>CredentialsProvider</key>
<dict>
<key>CognitoIdentity</key>
<dict>
<key>Default</key>
<dict>
<key>PoolId</key>
<string>YOUR COGNITO POOL ID</string>
<key>Region</key>
<string>YOUR REGION</string>
</dict>
</dict>
</dict>
</dict>
AWSCore/Service/AWSInfo.m
を読むとInfo.plistの解析の仕方が分かります。このAWSInfo
クラスは後述するインスタンスの取得時に利用されます。
2. [AWSServiceManager defaultServiceManager].defaultServiceConfiguration
にセットする
2.方法では、AWSServiceManager
シングルトンを利用します。
[AWSServiceManager defaultServiceManager]
はシングルトン取得メソッドで、このdefaultServiceConfiguration
も後述するインスタンス取得時に利用されます。
また、[AWSServiceManager defaultServiceManager].defaultServiceConfiguration
の実装(AWSCore/Service/AWSService.m
)を見てみると、
- (void)setDefaultServiceConfiguration:(AWSServiceConfiguration *)defaultServiceConfiguration {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_defaultServiceConfiguration = [defaultServiceConfiguration copy];
});
}
となっており、最初の一回しかシングルトンにセットできないことに注意したいです。
3. registerXxxxWithConfiguration:XxxxConfiguration:forKey:
メソッドを使って設定する
(Xxxxには各サービス名などが入ります)
3.の方法では、AWSServiceConfiguration
と同時にサービス固有コンフィギュレーションもセットします(おそらくほとんどのサービスクライアントで)。
1.と2.は各AWSサービスクライアントに共通して設定されますが、3.はサービス毎に個別に設定できます。これはインスタンスの取得方法に関係してきます。
サービスクライアントのインスタンス取得方法
インスタンスの取得方法は基本的に以下の2通りがあります。
-
defaultXxxx
メソッドでシングルトンを取得して使う -
registerXxxxWithConfiguration:XxxxConfiguration:forKey:
メソッドで生成したインスタンスをXxxxForKey:
メソッドで取り出して使う
1. defaultXxxx
メソッドでシングルトンを取得して使う
1.の方法では、まずAWSInfo
クラスを使いInfo.plistの設定情報を読み込もうとし、情報があれば使います。
Info.plistに設定情報がなければ、[AWSServiceManager defaultServiceManager].defaultServiceConfiguration
を使います。これは、インスタンスを取得する前に[AWSServiceManager defaultServiceManager].defaultServiceConfiguration
にコンフィグをセットしておかなければいけないことを意味します。そのため、コンフィグの設定はAppDelegate
のapplication:didFinishLaunchingWithOptions:
メソッドの早い段階で実行するのが確実だと思います。
なお、Info.plistにもdefaultServiceConfiguration
にも設定情報がなければ、例外を投げるといった実装になっています。
2. registerXxxxWithConfiguration:XxxxConfiguration:forKey:
メソッドで生成したインスタンスをXxxxForKey:
メソッドで取り出して使う
2.の方法では、引数に指定したコンフィギュレーションを使うので特に難しくないと思います。指定したコンフィギュレーションでインスタンスを初期化し、指定キーと紐付けてstaticなディクショナリに格納してインスタンスを保持します。XxxxForKey:
メソッドで指定したキーでディクショナリを引きインスタンスを取得します。
ちなみに、registerする前にXxxxForKey:
メソッドで取り出そうとすると、Info.plistから設定情報を読み込んでインスタンスを初期化します。個人的には例外を投げて落としてくれたほうがうれしいですが。
なお、1の方法では、サービス固有コンフィギュレーションは(おそらく多くの場合は)デフォルト値がインスタンス初期化時に適用されます。この場合、カスタマイズなサービス固有コンフィギュレーションはセットできないと思いましたが、AWSDynamoDBObjectMapper
はsaveやremoveといったメソッドを実行する時にサービス固有コンフィギュレーションを渡すことができます。この辺はクライアントごとに実装を詳しく知る必要がありますね。
まとめ
まとめると、公式ドキュメントにもあるように、AppDelegate
のapplication:didFinishLaunchingWithOptions:
メソッドでdefaultServiceConfiguration
の設定をし、サービスクライアントを使うシーンでシングルトンを取得するのが素直な使い方に思えます。
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc]
initWithRegionType:YOUR_REGION identityPoolId:YOUR_COGNITO_POOL_ID];
AWSServiceConfiguration *serviceConfig = [[AWSServiceConfiguration alloc] initWithRegion:YOUR_REGION
credentialsProvider:credentialsProvider];
[AWSServiceManager defaultServiceManager].defaultServiceConfiguration = serviceConfig;
...
}
// DynamoDBを使う場合
AWSDynamoDBObjectMapper *serviceClient = [AWSDynamoDBObjectMapper defaultDynamoDBObjectMapper];
...
また、registerXxxxWithConfiguration:XxxxConfiguration:forKey:
を使うのは個別にコンフィギュレーションをセットしたい場合でしょうか。
[AWSServiceManager defaultServiceManager].defaultServiceConfiguration
がシングルトンで各サービスに横断的に利用されるのは便利である反面、いつどこでクライアントに設定が反映されるのか、ちょっとソースコードを読まないと分からなかったので、今回は良い勉強になりました。
ちなみに、AWS Mobile Hubのインテグレーションガイドに従うとInfo.plistに書くように誘導されがちですが、Info.plistはipaファイルから簡単に抽出できてしまうので、あまり良くないと思っています。