[Swift3.0]iOS・tvOSアプリで画像を扱うときは、UIImageのキャッシュに要注意

  • 5
    いいね
  • 0
    コメント

メモリ使用量が激増!?

tvOSとiOSに対応した浮世絵時計アプリを開発しているときに、メモリ使用量がどんどん増えていく現象がおきて困っていました。

メモリリークしているわけではないのになぜだろう?と、いろいろ調べてみると、こちらの記事に出会いました。
UIImage using contentsOfFile - stack overflow

どうやら、UIImage(named: )をつかうと、自動的に画像がキャッシュされるようです。

アップルのドキュメントも調べてみると、このように書いてありました。

Use the init(named:in :compatibleWith:) method (or the init(named:) method) to create an image from an image asset or image file located in your app’s main bundle (or some other known bundle). Because these methods cache the image data automatically, they are especially recommended for images that you use frequently.

キャッシュしてほしくないときもある

頻繁にアクセスする画像なら、自動的にキャッシュしてくれると、読み込みが速くなるのでありがたいです。

しかし、浮世絵時計アプリは、200枚近くの浮世絵画像読み込んでいきます。それを全部キャッシュするものですから、浮世絵をひととおり表示すると、使用メモリが300MBくらいになってしまいました。

2週目からは、キャッシュがきいているため使用メモリが増えないのですが、いくらなんでも300MBもメモリをつかうのは、モバイルアプリとしては困ったちゃんです。それに、これからのアップデートで浮世絵画像を追加すると、そのたびに使用メモリが増えることになってしまいます。

キャッシュしない方法

それでは、自動的にキャッシュをしてほしくない場合には、どうすればいいのでしょうか?

さらにアップルのドキュメントを調べてみると、キャッシュをしない場合はUIImage(contentsOfFile: )を使ってね、と書いてあります。

Use the imageWithContentsOfFile: or init(contentsOfFile:) method to create an image object where the initial data is not in a bundle. These methods load the image data from disk each time, so you should not use them to load the same image repeatedly.

コードを書きかえて実際に試してみると、確かにキャッシュされていないようで、使用メモリがどんどん増えていくことはなくなりました。

これでバンバンザイのようですが、ひとつだけ困ったことがあります。

それは、contentsOfFileをつかうとassetカタログがつかえないのです。

Kobito.BROmZo.png

アプリの仕組みとして、assetカタログをつかえなくて困ることは(いまのところは)ありません。しかし、Xcodeで画像を管理しやすいので、assetをつかいたい。でも、それだとメモリを山盛りつかってしまう。

というジレンマで悩みましたが、背に腹はかえられません。

しかたないので、imagesフォルダをつくって、そのなかに画像ファイルをいれることにしました。

Kobito.gtN0ZA.png

というわけで、たくさんの画像をあつかうアプリを開発する際は、UIImageのキャッシュには十分ご注意ください。