[iOS 8/Xcode 6] Today Extension のメモリ容量制限について調べてみた

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Today Extension がうまく表示されない事案

Today Extension を使用したアプリを開発中、以下の様な現象に遭遇しました。

  • Today Extension 表示領域に何も表示されず、「読み込めません」とのみ表示される
  • 表示領域が確保されず、Today Extension の Bundle display name のみが表示される
  • これらは、最初原因がわからず苦労しました。

    どうやら、扱っている画像リソースファイルの容量が大きいほど、Today Extension の動作が不安定になるらしいことがわかってきました。

    Apple のドキュメント

    以下のように、Apple のドキュメントにこの件にいて書かれていました。

    では、どれくらいの容量の画像を扱った場合に、正常に動作しなくなるのか。実際に実験してみることにしました。

    Extensionsに割り当てるメモリ量は、フォアグラウンドで動作するアプリケーションに比べ てかなり制限されます。iOSでもOS Xでも、ユーザがホストアプリケーションでの作業に戻ろうと すると、システムがExtensionを積極的に停止させることがあります。中でも特にメモリ量の制限がきついExtensionがあります。たとえばウィジェットは、同時にいくつも開くことが多いので、特にメモリ効率を意識しなければなりません。

    App Extensionsプログラミングガイド

    GPUは、システムの共有リソースであることに注意してください。App Extensionsは共有リソー スを優先的に使えるわけではありません。たとえば、グラフィックスを多用するゲームを 「Today」ウィジェットとして実装すると、使い勝手が悪くなる可能性があります。システムはメ モリ不足のため、そのようなExtensionを停止することもあります。システムのリソースを多用する機能は、App Extensionsではなくアプリケーションに適しています。

    App Extensionsプログラミングガイド

    実験内容

    複数の画像ファイルを用意します。ピクセル数・容量が異なり、一番小さいもので100×100 pixel(13KB)、一番大きなもので2400×2400 pixel(5.8MB)です。

    001

    今回の実験に使うアプリのフォルダ構成です。
    ViewController は Swift で書いています。

    表示される画像を変更するボタンと、画像・取得メモリ量を表示するのみのシンプルなものです。

    確保しているメモリ量を取得するクラス(Memory)は Objective-C で書かれていまして、Bridging Header を使い Swift コードから使用しています。

    この部分は、shu223 氏が執筆された以下の記事を参考にコーディングさせていただきました。

    Instrumentsを使用せず、プログラムから空きメモリ量や使用中のメモリ量、CPU負荷を取得する

    実機編(iPhone 5s)

    今回は、手持ちの iPhone 5s を使います。

    アプリ側のスキームで実行

    スクリーンショット 2014-11-18 14.24.34

    スキームを切り替え、アプリのターゲットをビルド・実行してみます。
    起動後、Todayの画面を表示させ、ウィジェットを追加し、実験開始です。

    数秒ごとに確保しているメモリ量(Bytes)の表示を更新しています。
    100〜2100までの各ボタンが、それぞれ縦横100 pixelの画像〜縦横2100 pixelの画像に対応していて、タップすると左上の画像が入れ替わります。 ただし、見かけ上の大きさは AutoLayoutで WidthとHeightの値を指定してあるので、変わりません。

    100, 300 pixel

    IMG_3702

    確保量が少し増えましたが、動作に変化ありません。

    600 pixel

    IMG_3704

    さらに確保量が増えましたね。こちらも普段通り。

    1200 pixel

    IMG_3705

    1200 pixelの画像が表示されず、一瞬、表示領域からすべての表示が消えました。

    1秒後に表示が復活しますが 100 pixel画像が表示されています。ウィジェットが一度終了し、再度起動したようです。

    2100 pixel

    IMG_3706

    「読み込めません」と、Today領域に表示されてしまいました。

    文字の表示がされず、領域のみが確保されている状態になることもあります。

    Today Extensionのスキームで実行

    スクリーンショット 2014-11-18 14.25.13

    さらにスキームを切り替え、Todayのターゲットを実行してみます。

    100, 300 pixel

    IMG_3711

    確保量が少し増えましたが、動作に変化ありません。

    600 pixel

    IMG_3713

    さらに確保量が増えましたね。こちらも普段通り。

    1200 pixel

    IMG_3714

    おっと、こちらも問題ありません。

    2100 pixel

    IMG_3715

    なんとここまでメモリを確保しても問題なく動作しています。 どうやら、Today Extension のスキームを指定して実行すると、メモリの縛りがゆるくなるようです。
    Today Extension のログを出力するには、Today Extension のターゲットを指定する必要があります。ログ出力は大変便利です。しかし、実際よりも潤沢なメモリ上でTodayが動作するため、動作テストが十分に行えない可能性があります。

    おわりに

    他のiOSデバイスではどうなるのかなど、まだ調べたりないことがあります。 こちらはまたの機会に試してみたいと思います。