Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
37
Help us understand the problem. What is going on with this article?

More than 5 years have passed since last update.

@_tid_

WatchKitでWatchに画像をキャッシュする

WatchKitでは明示的にWatchに画像をキャッシュする方法が用意されています。
使用方法と、なぜ画像のキャッシュが必要なのかをまとめてみました。

2014/12/15[修正]Xcode6.2β2でキャッシュに追加するメソッドに戻り値が追加されたので一部記述を修正しました。

画像をキャッシュする方法

WKInterfaceDeivceクラスの下記メソッドがキャッシュ関連のメソッドです。

func addCachedImage(_ image: UIImage!, name name: String!) -> Bool
func addCachedImageWithData(_ imageData: NSData!, name name: String!) -> Bool
func removeCachedImageWithName(_ name: String!)
func removeAllCachedImages()

キャッシュは最大 20 MB で、超過した場合は古い物から順に消されるとのこと。
なお、シミュレータ上ではこの制限を超過しても消されることはありませんでした。

WKInterfaceDeviceクラスとは?

Watchの情報をカプセル化して提供してくれるクラスです。
キャッシュ関連のメソッドの他、画面サイズやロケール情報などを提供してくれます。
このクラスは、サブクラスを作ったりインスタンスを作ってはいけません。

currentDeviceクラスメソッドを用いてインスタンスを取得します。

let device = WKInterfaceDevice.currentDevice()

画像をキャッシュしてみる

// 新しくキャッシュする
let imageDog = UIImage(named: "dog")  // WatchKit ExtensionのアセットからUIImageを作る
device.addCachedImage(imageDog, name: "bowwow") // キャッシュする

既に同名のキャッシュが存在する場合、更新は行われず古いキャッシュがそのまま残ります。

キャッシュを更新してみる

キャッシュを更新する場合、先に古いキャッシュを消す必要があります。

// キャッシュを更新する
device.removeCachedImageWithName("bowwow")      // 古いキャッシュを消す
device.addCachedImage(imageDog, name: "bowwow") // キャッシュする

キャッシュした画像を使ってみる

WKInterfaceImageクラスのsetImageNamed(_ imageName: String!)メソッドでキャッシュした画像が使われます。
なお、このメソッドはWatch Appに含めたアセットを使う場合にも使います。
アセットとキャッシュ、どちらにも存在しない場合はsetImage(nil)した時と同じ挙動になるようです。

@IBOutlet weak var image: WKInterfaceImage!
image.setImageNamed("bowwow")

キャッシュとアセットの関係について

前述の通り、WKInterfaceImageクラスのsetImageNamed(_ imageName: String!)メソッドは
アセットを使う時とキャッシュを使う時のどちらでも使える共通のインターフェースとなっています。
そのためかアセットとして存在している名前をキャッシュ名として使用することはできなくなっています。

例えば"cat"という名前のアセットが存在する場合、"cat"という名前のキャッシュは作成できません。
またこの時、"cat"という名前のキャッシュを削除しようとしても(当然ですが)何も効果がありません。
エラーハンドリングできないので注意が必要です。
→Xcode6.2βから、キャッシュ追加時にBool値で判定できるようになりました。

キャッシュの生存期間(不明)

キャッシュした画像がアプリ終了後も残るのか、
公開されているドキュメント内で明確な記述を見つけられませんでした。

リファレンスの一文を見るとなんとなく永続化してくれそうな気もします。

Each app receives 20 MB of cache storage. -WatchKit Framework Reference

なぜキャッシュが必要なのか

なぜこのようなキャッシュが必要なんでしょうか? 理由は下の図を見ると分かります。

WatchKit Programming Guideから引用
app_communication_2x.png

WatchKit Extension(コード/リソース)はiPhone側にあります。そのため、リソースは
Watch Appが保持しているリソースを除いてiPhoneからWatchKit経由でWatchに転送されます。
この時にWatchにキャッシュしてしまえば、1回目以後転送が発生しないというわけです。

iPhoneから何度もリソースを転送するより、
Watchにキャッシュしておいてそこから取り出す方が速いし電力消費も少ないと考えられます。
だからキャッシュが必要なんだと思います。

キャッシュが必要な画像、不要な画像

動的な画像で2回以上使う物は可能な限りキャッシュする。
静的な画像はWatch Appに含めるようにしてキャッシュしない。(する必要がない)

後は、アプリの仕様と実機の特性にあわせて最適化することになりそうです。

まとめ

キャッシュは実機上で動かすまで効果を感じられないかもしれません。
それでも、もし早期のアプリリリースを目指すなら覚えておきたいポイントだと思います。

参考:
WatchKit Programming Guide
WatchKit Framework Reference > WKInterfaceDevice Class Reference

37
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
37
Help us understand the problem. What is going on with this article?