ラベル Xcode の投稿を表示しています。 すべての投稿を表示
ラベル Xcode の投稿を表示しています。 すべての投稿を表示

2014年11月8日土曜日

SKProductsRequestでハマった。抜け出したけど。

前回に引き続き、iOSアプリの開発ネタです。初めてっていうのは、いろいろな問題にぶち当たりますな。

原因不明でアプリがクラッシュすることが何度かあり、どうやら、アプリ内課金の関係で、Appleのサーバに問い合わせに行っている最中に、「遅い!もういいよ!」みたいな感じで画面遷移(具体的には、ナビゲーションの「戻る」を押す)をしてしまうと、ごく稀にこの問題が発生する、ということまで絞り込むことができた。
ごく稀にというのが、まあ、厄介なところ。

ちなみに、アプリがクラッシュした時のXcode(ちなみにバージョンは6.1)の表示はこんな感じ。

コードがこれ↓


スタックがこれ↓


これだけだと、さっぱり、意味がわからない。

"Enqueued from com.apple.root.default-qos"と"EXC_BAD_ACCESS"とかでググっても、なかなかこれというのが見つからないし、なんと言っても、"Enqueued from com.apple.root.default-qos"と"SKProductsRequest"の組み合わせで検索結果がゼロというのに参った。
SKProductsRequestのstartメソッド呼ばない限りクラッシュしないので、この関係だってことは間違い無いと思うんだけど…。

そして、結局、自分で、何が原因なのかわかりました。ので、情報共有です。

こんなコードを書いていたんですよ。どこかで見たコードのコピペですけど。
- (void)startRequest
{
    SKProductsRequest* productRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithArray:productIdentifiers]];
    productRequest.delegate = self;
    [productRequest start];
}
これだと、サーバからのレスポンスを受け取った時に、selfがdeallocateされてしまった後だと、まずいことになるんですよね。productRequestの後始末が考慮されていない。

というわけで、僕が採った解決法はこれ。
まず、ヘッダファイルでこんな宣言。
@property (nonatomic, strong) SKProductsRequest *productRequest;
そして、本体コードでは、
- (void)startRequest
{
    _productRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithArray:productIdentifiers]];
    _productRequest.delegate = self;
    [_productRequest start];
}


これに加えて、viewWillDisappearで、delegateを無効化してやる処理を加えました。
- (void)viewWillDisappear:(BOOL)animated { _productRequest.delegate = nil; [[SKPaymentQueue defaultQueue] removeTransactionObserver:self]; }


そしたら、(今のところ?)ばっちり、っぽいです。なんか自信なさげな書き方で恐縮ですが。いかんせん、稀にしか起こらない問題なので断言が難しいのです。

iOSアプリでの各国語対応。なるほど、そうだったのか。

久しぶりにブログ書きます。
ちなみに、会社で、仕事の一環として、時々英語でブログ書かされたりしてるんですが、なんていうか、仕事で書くのって気が重いですね。ま、それはさておき。

実は、内緒にしていましたが、ここ最近、iOSアプリを作ってたんです。初めての。
それで、一応、大した手間じゃないので、各国語対応させてみよう、と、ということで、ベース言語(実際は英語で記述)、それに加えて日本語用の文字列ファイルを用意しました。

今まで、「iPhoneの使用言語」として日本語と英語を設定してそれぞれでの表示を試してみては、ふむふむ、うまくいっておるわい、と思っていたのですが、先ほど、iPhoneの使用言語をイタリア語に設定してみると、期待に反してなんと日本語の文字列が表示されてしまうではないですか。
うーむ、何か間違った設定をしているのだろうかと軽くググってみたけれども、うまく期待する答えにたどり着けない。

結局、自分で原因がわかって全て丸く収まりました。
こういうことです。↓

設定言語を、英語⇒日本語⇒イタリア語、という順で変更すると、「使用する言語の優先順位」(設定アプリの「一般>言語と地域」の中にある)が

  1. イタリア語
  2. 日本語
  3. 英語

となってしまうんですね。自動で。

この状況で、アプリがイタリア語にローカライズされていないからアプリのベース言語(つまり英語)が選ばれるかと予想していたのですが、そうではなく、英語よりも高い優先度で日本語を使う設定に(iOSの判断によって)なっているので、日本語が表示される、と。そういうことでした。
つまり、「iPhoneの使用言語」よりも「使用する言語の優先順位」のほうが意味がある、と。

ここで、仮に、日本語(と英語の両方)が「使用する言語の優先順位」に含まれていない場合、ベース言語(つまり英語)が表示されるんでしょうね。
試してみたいのですが、「使用する言語の優先順位」は手動で編集できないので、残念です。

ところで15年ぐらい前はローカライズを"l10n"、国際化を"i18n"とか表記してたんですけど、これって今の若い人にも通じるんでしょうかね。逆に、今では別の表記をしているなら、それを知りたい。
ちなみに由来は
"localization"⇒"lxxxxxxxxxxn"(LとNの間に10文字)⇒"l10n"
"internationalization"⇒"ixxxxxxxxxxxxxxxxxxn"(IとNの間に18文字)⇒"i18n"
なので、表記が"l10n"や"i18n"であっても、「えるじゅーえぬ」「あいじゅーはちえぬ」などと読むことはなく、よみがなとしてはやはり「ろーからいぜーしょん」「いんたーなしょならいぜーしょん」でした。少なくとも僕の周辺では。