2012年10月
« 9月   11月 »
1234567
891011121314
15161718192021
22232425262728
293031  
2012/10/18

非Retina画像を削除してiOSアプリの容量を減らす

RetinaディスプレイをサポートしたiOSアプリには2つのサイズの画像を入れることになってます。

例えばフルスクリーン表示の画像が有ったとすると、以下の二つを入れることになります。(一旦iPhone 5のサイズはおいておきます)

・filename.png (320×480px)
・filename@2x.png (640×960px)

 

iPhoneに関しては、iPhone 4でRetinaディスプレイに対応してから随分経ちますし、iPhone 3GS以前の非RetinaのiPhoneを使っているユーザーも少しづつ減って来てるだろうと考えると、非Retina向けの画像をバンドルせずに、アプリの容量を減らせるとちょっと幸せなのではないかと考えて、ちょっとした仕組みを考えてみました。

 

ネットワークを使ったゲームの場合は、初回起動時にRetinaか非Retinaの素材をダウンロードして使うように作ることで、アプリの容量自体は減らせると思いますが、アプリ落とすのに待たされて、さらにアプリを起動した後に待たされて、っていうのはなかなかユーザーに優しく無い。

個人のデベロッパーの場合は、サーバーにリソース上げてダウンロードさせるというのもちょっと手間。

ってことで、通信を使わなくてもいい仕組みを作ってみました。

 

実は、単純にプロジェクトから非Retinaの画像を消してみても、UIImageViewは動くには動きました。

UIImageクラスは、非Retina向けの画像ファイルが無い状態で、@2xが付いたファイルだけある場合は、@2xの方を読み込むように出来ている様です。

ただ、この場合画面サイズより大きいサイズの画像を読み込んで、縮小して表示している状態になるので、少なくとも使用メモリは大きくなり、アプリによってはメモリが足りなくなる可能性があります。

 

そこで単純な仕組みを考えてみました。

 

非Retina端末で、Retina画像しか無い場合は、Retina画像を縮小して通常サイズの画像を作って使用するUIImageを継承したクラス(RetinaImageクラス)を作りました。

初めて画像を読み込む時にRetina画像を読み込んだり、縮小処理を行うためにメモリや処理時間を食いますが、2回目以降は縮小済みのキャッシュした画像を読み込むため、通常の動作とあまり変わり有りません。(厳密にはファイルの存在チェックなど行っている分、UIImageで読み込むよりは遅くなりますが、よほどの量を読み込まない限りは体感できない差だと思います。)

 

Storyboardを使った開発では、UIImageViewを使うので、こちらも対応方法は無いかと試行錯誤してみました。

Nibファイルから初期化される時に呼ばれるinitWithCoderでUIImageのファイル名を取得する方法が無いので、User Defined Runtime Attributesを使うという面倒な実装になってしまいましたが、UIImageViewを継承したクラス(RetinaImageViewクラス)を作って対応できました。

 

Storyboardで画像を使うクラスでは、UIButtonもありますが、UIImageViewと同じ手法で実装できると思います。

 

非Retina画像の中でも容量の大きな画像のところだけ使うというような使い方もできます。

 

以上のクラスや使い方など一式まとめたものを、前から気になってたGumroadで売ってみようかとアップしてみました。

iOSアプリで非Retina画像をバンドルせずに容量を減らすためのクラス&利用の手引き

これで実装して問題無く動くかは、一画面で読み込む画像の量など、アプリによっても事情が違うかも知れませんので、ご利用は自己責任でお願いします。

 上記の説明で何をやってるかが想像できる人に取っては大したプログラムではないので、作った方が早い可能性もありますが、315円なら悪く無い値段じゃないかなーと思って、315円にしてみました。

 

ZIPには以下が含まれています。

 

・RetinaImage / RetinaImageViewクラスのソース

利用を特に制限するつもりはありませんので、改変などして自由に使って頂いて構いません。

 

・Retina画像から非Retina画像を作るAutomatorプログラム

Retina画像が入っているフォルダを、Automatorプログラムのアイコンへドラッグ&ドロップすると、非Retina向けに縮小した画像ファイルを作ります。(ファイル名中の@2xも取り除いたものができます)

 

・RetinaImge / RetinaImageViewクラスを使ったサンプルプロジェクト

非Retina画像を削除した状態で、UIImageで読み込んだ場合と、RetinaImageで読み込んだ場合の比較や、StoryboardでRetinaImageViewを使ったサンプルです。

 

・readme.html

ZIPの中身の説明やクラスの使い方の説明など書きました。

 

その他、プログラム初心者の方には、RetinaImageクラス内で行っている以下の処理も役に立つかも知れません。

・オフスクリーンでの画像の描画/合成処理(拡大/縮小/回転して描画もできます)

・キャッシュディレクトリへのデータの保存と読み込み処理

・UIImageをPNGファイルで保存する処理

 

大したことはやってないんですが、良かったら使ってみて下さい。

iOSアプリで非Retina画像をバンドルせずに容量を減らすためのクラス&利用の手引き

疑問点など何かありましたら、こちらの記事のコメント欄でお願いします。

 


※iPhoneアプリ開発に関する投稿を今から始めるiPhoneアプリ開発にまとめました。

Comments are closed.