StoreKitでは、支払いリクエストをする前にプロダクト情報を取得しにいくようにドキュメントに書かれています。プロダクト情報をAppStoreのサーバーに取りにいき、返ってきた情報を基にUIを更新し、また支払いのリクエストを発行するように指南されています。
プロダクト情報の取得方法
StoreKitにはSKProductsRequestというクラスがあり、これを使います。プロダクト情報を取得してくる、といってもAppStoreに登録したプロダクトの一覧を返してくれるわけではなく、自分であらかじめ取得してきたいプロダクトのIDを指定しておくと、そのIDに対応するプロダクトの情報が返ってきます。
SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithObject: @"adfree"]]; request.delegate = self; [request start];
ちなみに、IDはNSSetなので複数同時に渡せます。情報の取得が完了したときの通知先をdelegateプロパティでセットしたら、startします。情報の取得が完了すると、delegateオブジェクトで
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
が呼び出され、引数responseからプロダクトの情報を含む様々な情報を取得することができます。SKProductRequestDelegateプロトコルはSKRequestDelegateに準拠しているため、オフライン等でリクエストが失敗した場合は、
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error
が呼ばれます。
もっとkwsk
ここまでの流れでは、まだ大きな疑問や問題はありません。しかし実際にアプリに組み込もうとすると、早速ここからちょっとした問題や疑問が出てきます。
1. 遅い
自分が最初にアプリにアイテム販売を組み込もうとしたとき、In App Purchase Programming Guideに素直に従い、アイテム一覧画面でプロダクト情報を取得しにいくようなプログラムを組んでみたところ、表示されるまでの時間が長い(数秒程度)ことが問題になりました。
厄介な事に、このSKProductRequestはアプリを起動して一回目の呼び出しは数秒程度時間がかかるのです。おそらくAppStoreサーバーと認証を行い、セッション等を生成しているのではないかと予想しています。手元で実験してみた感じでは、一回目のリクエストは3-5秒程度のレスポンスまでに時間があったのに対し、2回目以降は1秒かからずにレスポンスがくるようになります。
UIの表示に3-5秒かかるのは、実際に使ってみると結構ストレスを感じます。そこで、プロダクト情報取得をアイテム購入画面表示時ではなく、アプリ起動時にあらかじめ取得して保持しておくことを考えました。
2. 有効期間と情報更新
ただし、あらかじめ取得しておくだけでは問題があります。起動時に取得したタイミングでの情報と、ユーザが購入ボタンを押したタイミングでの情報に差異が生まれてしまう可能性があることです。(デベロッパが値段を変更した場合など)。勿論これは確率の問題であって、購入直前に取得したとしても起こりうる問題ではありますが。
試行錯誤してみた結論としては、幸い二回目以降のリクエストは高速でレスポンスが返ってくるため、この問題を考えると「起動時に一回リクエストを投げておいた上で、表示のタイミングでもリクエストを投げる」というのが妥当そうです。
なお、ここで取得したプロダクト情報は支払いリクエストの際にも使います。その際にも基本的には再度購入直前にプロダクト情報を取得しなおしにいく方が安全そうです。
そんなに何度もリクエストを投げまくってよいのか、という疑問はありますが…。
3. 通貨は?
ちなみに、取得されるSKProductには価格の情報が含まれています。ユーザがApple IDでログイン済みの場合は、そのユーザにあった通貨で自動的に取得されているようですが、ユーザがログインしていない場合については、確認してみた限りでは前回ログインしたユーザの通貨で取得されるようです。一度もApple IDでログインしたことがない端末…についてはさすがに手元になかったので確認できず…。
結論
というわけで、プロダクト情報の取得については初回リクエスト時の遅延の部分さえ注意していれば、特に大きな問題はなさそうです。デリゲート形式だと使い勝手が悪いのは事実なので、余裕があれば自前でブロック対応の関数を用意すると便利になりますが、今回は省略。次は支払いリクエストを作成する部分を見ていきます。
課金コンテンツのプロダクト情報の取得は2回目は高速に動くらしい。
「起動時に一回リクエストを投げておいた上で、表示のタイミングでもリクエストを投げる」
現時点ではこれはかなり有効かもしれない。描画で5秒待ちはちょっとシンドイね。
http://t.co/9EEYCFke