【WatchKit】Apple WatchにWebの画像を読み込む

つみきでアプリエンジニアをしている野田です。
早速ですが、もうすぐApple watchが発売になります! 今までにないユーザー体験をもたらしてくれるんだろうとユーザーとしても開発者としてもワクワクしています。
この新しい体験を自分でも開発したいと思い、Apple WatchのWatchKit Frameworkを触っています。
そこで、Apple WatchにWebからURLを指定して画像を読み込む実装について紹介したいと思います。

Webから指定したURLの画像を読み込む

filmarksSampleIcon.png

例としてWebから取得したFilmarksのロゴをApple Watch側で表示してみたいと思います。
画像の読み込みはiPhoneの実装でもおなじみのNSURLSessionDataTaskを使って読み込みます。
WathKit側にそれ用の特別なAPIがあるわけではなく、今までのiPhoneの実装通りに書くことができます。

@IBOutlet weak var sampleImage: WKInterfaceImage!

// 画像を読み込むメソッド
func hogeMethod () {
    let imageURL = NSURL(string: "http://blog.tsumikiinc.com/upload/img/filmarksSampleIcon.png")
    self.setImageURL(imageURL)
}

func setImageURL(URL: NSURL!) {

    let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
    let dataTask = session.dataTaskWithURL(URL, completionHandler: {
        (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
        if let image = UIImage(data: data) {
            dispatch_async(dispatch_get_main_queue()) { [weak self] in
                if let weakSelf = self {
                    weakSelf.sampleImage.setImage(image)
                }
            }
        }
    })
    dataTask.resume()
}

これで、Web上にあるアイコンをApple watch側で表示することができます。

スクリーンショット 2015-04-16 15.51.50.png

しかし、この方法では画像を表示する際毎回ネットワークを通して取得しなくてはいけません。
そこで、一度取得した画像をキャッシュして再度表示する際に、キャッシュがあればそちらから読み込むように実装を変更します。

画像をキャッシュして再利用する

WatchKitでは画像のキャッシュはWKInterfaceDevice

  • addCachedImage(_:name:)
  • addCachedImageWithData(_:name:)

を使い、保存したい画像もしくはデータに名前を関連づけてキャッシュ画像にすることができます。
また、キャッシュ画像があるかどうかは

  • cachedImages

というDictionary型のPropertyから追加する際の名前を使って確認することができます。
それらを用いて先ほどのsetImageURLメソッドを以下のように書き換えます。

func setImageURL(URL: NSURL!) {

        let cacheKey = URL.absoluteString!
        let device = WKInterfaceDevice.currentDevice()

        if (device.cachedImages[cacheKey] != nil) {
            println("use cache")
            self.sampleImage.setImageNamed(cacheKey)
        }
        else {
            println("load image")
            let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
            let dataTask = session.dataTaskWithURL(URL, completionHandler: {
                (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
                if let image = UIImage(data: data) {
                    dispatch_async(dispatch_get_main_queue()) { [weak self] in
                        if let weakSelf = self {
                            weakSelf.sampleImage.setImage(image)
                            if (!device.addCachedImage(image, name: cacheKey)) {
                                device.removeAllCachedImages()
                                device.addCachedImage(image, name: cacheKey)
                            }
                        }
                    }
                }
            })
            dataTask.resume()
        }
    }

上記の実装で、キャッシュがある場合はキャッシュ画像を読み込み、ない場合はWebから取得するというふうにできます。
ただし、アプリでキャッシュする画像は5MBまでという制限があります。
そこで、キャッシュの追加に失敗した際は

  • removeAllCachedImages()

を使用して、一度全てのキャッシュ画像を削除して再度追加するようにしています。
この辺りは実際に実機が出た後に適切な処置に変えていければと思ってます。

まとめ

今回はWatchKitのAPIの一部の実装について紹介しました。 Apple Watchが発売されれば、今までシミュレーターでもやもやしていた部分が一気に解決し、 開発もより活発になっていくと思います。
自分もApple Watchを触り倒して新しいユーザー体験を生み出すようなアプリを開発していきたいです!

参考

Apple Watch Programming Guide

WatchKit Framework Reference

スマホアプリ制作、Web制作、UIコンサルなどのご依頼はこちら

お問い合わせ