Help us understand the problem. What is going on with this article?

【AWS Mobile SDK for iOS】AWSサービスクライアントの初期化と取得方法について調べたこと

More than 1 year has passed since last update.

はじめに

AWS Mobile SDKを使えば、S3やDynamoDBといったAWSサービスをアプリで直接利用できるようになります。これはとても便利なことなのですが、実際にコーディングする時、オンラインのドキュメントだけでは使い方がなかなか分かりにくかったので、ソースコードを読んで理解を深めた話です。
この記事ではサービスクライアントの初期化について書いています。

なお、AWS Mobile SDK for iOSのバージョンはv2.4.14で動作確認をしています。


各AWSサービスのサービスクライアントの初期化と取得には、いくつかの方法がありますが、基本的にはAWSServiceConfigurationとサービス固有のコンフィギュレーションをセットして利用します。

例えば、DynamoDBを操作するAWSDynamoDBObjectMapperならばサービス固有のコンフィギュレーションとしてAWSDynamoDBObjectMapperConfigurationが必要です。
また、サービス固有コンフィギュレーションは不要なクライアントもあります。
ちなみに、"サービス固有コンフィギュレーション"とは公式な呼び方ではなく、僕が勝手にそう呼んでいるだけです。

サービスコンフィギュレーションの設定方法

AWSServiceConfigurationをサービスクライアントに設定する方法は以下の3通りがあります。

  1. Info.plistに記述する
  2. [AWSServiceManager defaultServiceManager].defaultServiceConfigurationにセットする
  3. 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通りがあります。

  1. defaultXxxxメソッドでシングルトンを取得して使う
  2. registerXxxxWithConfiguration:XxxxConfiguration:forKey:メソッドで生成したインスタンスをXxxxForKey:メソッドで取り出して使う

1. defaultXxxxメソッドでシングルトンを取得して使う

1.の方法では、まずAWSInfoクラスを使いInfo.plistの設定情報を読み込もうとし、情報があれば使います。

Info.plistに設定情報がなければ、[AWSServiceManager defaultServiceManager].defaultServiceConfigurationを使います。これは、インスタンスを取得する前に[AWSServiceManager defaultServiceManager].defaultServiceConfigurationにコンフィグをセットしておかなければいけないことを意味します。そのため、コンフィグの設定はAppDelegateapplication:didFinishLaunchingWithOptions:メソッドの早い段階で実行するのが確実だと思います。

なお、Info.plistにもdefaultServiceConfigurationにも設定情報がなければ、例外を投げるといった実装になっています。

2. registerXxxxWithConfiguration:XxxxConfiguration:forKey:メソッドで生成したインスタンスをXxxxForKey:メソッドで取り出して使う

2.の方法では、引数に指定したコンフィギュレーションを使うので特に難しくないと思います。指定したコンフィギュレーションでインスタンスを初期化し、指定キーと紐付けてstaticなディクショナリに格納してインスタンスを保持します。XxxxForKey:メソッドで指定したキーでディクショナリを引きインスタンスを取得します。

ちなみに、registerする前にXxxxForKey:メソッドで取り出そうとすると、Info.plistから設定情報を読み込んでインスタンスを初期化します。個人的には例外を投げて落としてくれたほうがうれしいですが。

なお、1の方法では、サービス固有コンフィギュレーションは(おそらく多くの場合は)デフォルト値がインスタンス初期化時に適用されます。この場合、カスタマイズなサービス固有コンフィギュレーションはセットできないと思いましたが、AWSDynamoDBObjectMapperはsaveやremoveといったメソッドを実行する時にサービス固有コンフィギュレーションを渡すことができます。この辺はクライアントごとに実装を詳しく知る必要がありますね。

まとめ

まとめると、公式ドキュメントにもあるように、AppDelegateapplication: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ファイルから簡単に抽出できてしまうので、あまり良くないと思っています。

参照

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした