[iOS 8/Xcode 6] Today Extension のメモリ容量制限について調べてみた
Today Extension がうまく表示されない事案
Today Extension を使用したアプリを開発中、以下の様な現象に遭遇しました。
これらは、最初原因がわからず苦労しました。
どうやら、扱っている画像リソースファイルの容量が大きいほど、Today Extension の動作が不安定になるらしいことがわかってきました。
Apple のドキュメント
以下のように、Apple のドキュメントにこの件にいて書かれていました。
では、どれくらいの容量の画像を扱った場合に、正常に動作しなくなるのか。実際に実験してみることにしました。
Extensionsに割り当てるメモリ量は、フォアグラウンドで動作するアプリケーションに比べ てかなり制限されます。iOSでもOS Xでも、ユーザがホストアプリケーションでの作業に戻ろうと すると、システムがExtensionを積極的に停止させることがあります。中でも特にメモリ量の制限がきついExtensionがあります。たとえばウィジェットは、同時にいくつも開くことが多いので、特にメモリ効率を意識しなければなりません。
GPUは、システムの共有リソースであることに注意してください。App Extensionsは共有リソー スを優先的に使えるわけではありません。たとえば、グラフィックスを多用するゲームを 「Today」ウィジェットとして実装すると、使い勝手が悪くなる可能性があります。システムはメ モリ不足のため、そのようなExtensionを停止することもあります。システムのリソースを多用する機能は、App Extensionsではなくアプリケーションに適しています。
実験内容
複数の画像ファイルを用意します。ピクセル数・容量が異なり、一番小さいもので100×100 pixel(13KB)、一番大きなもので2400×2400 pixel(5.8MB)です。
今回の実験に使うアプリのフォルダ構成です。
ViewController は Swift で書いています。
表示される画像を変更するボタンと、画像・取得メモリ量を表示するのみのシンプルなものです。
確保しているメモリ量を取得するクラス(Memory)は Objective-C で書かれていまして、Bridging Header を使い Swift コードから使用しています。
この部分は、shu223 氏が執筆された以下の記事を参考にコーディングさせていただきました。
Instrumentsを使用せず、プログラムから空きメモリ量や使用中のメモリ量、CPU負荷を取得する
実機編(iPhone 5s)
今回は、手持ちの iPhone 5s を使います。
アプリ側のスキームで実行
スキームを切り替え、アプリのターゲットをビルド・実行してみます。
起動後、Todayの画面を表示させ、ウィジェットを追加し、実験開始です。
数秒ごとに確保しているメモリ量(Bytes)の表示を更新しています。
100〜2100までの各ボタンが、それぞれ縦横100 pixelの画像〜縦横2100 pixelの画像に対応していて、タップすると左上の画像が入れ替わります。
ただし、見かけ上の大きさは AutoLayoutで WidthとHeightの値を指定してあるので、変わりません。
100, 300 pixel
確保量が少し増えましたが、動作に変化ありません。
600 pixel
さらに確保量が増えましたね。こちらも普段通り。
1200 pixel
1200 pixelの画像が表示されず、一瞬、表示領域からすべての表示が消えました。
1秒後に表示が復活しますが 100 pixel画像が表示されています。ウィジェットが一度終了し、再度起動したようです。
2100 pixel
「読み込めません」と、Today領域に表示されてしまいました。
文字の表示がされず、領域のみが確保されている状態になることもあります。
Today Extensionのスキームで実行
さらにスキームを切り替え、Todayのターゲットを実行してみます。
100, 300 pixel
確保量が少し増えましたが、動作に変化ありません。
600 pixel
さらに確保量が増えましたね。こちらも普段通り。
1200 pixel
おっと、こちらも問題ありません。
2100 pixel
なんとここまでメモリを確保しても問題なく動作しています。
どうやら、Today Extension のスキームを指定して実行すると、メモリの縛りがゆるくなるようです。
Today Extension のログを出力するには、Today Extension のターゲットを指定する必要があります。ログ出力は大変便利です。しかし、実際よりも潤沢なメモリ上でTodayが動作するため、動作テストが十分に行えない可能性があります。
おわりに
他のiOSデバイスではどうなるのかなど、まだ調べたりないことがあります。 こちらはまたの機会に試してみたいと思います。