ごんれのラボ

iOS、Android、Adobe系ソフトの自動化スクリプトのことを書き連ねています。

Watchアプリのラベルに表示した文字列を横スクロールさせる

概要

Qiitaにあげた記事の転記。(一部変更点あり)

qiita.com

Watchアプリのラベルに表示した文字列を横スクロールさせたいという要望があったので、WKInterfaceLabelのExtensionで実現した。

サンプル動画

仕様など

  • スクロールは、一定時間おきに文字列の左端を削除することで実現
  • エンドレス版は、削除した文字列を末尾に追加し、電子掲示板のような動きにした

留意点

いくつか留意すべき点がある。

表示する文字列がラベルに収まる長さかどうかの判定ができない

UILabelでは、自身のframeのwidthと表示する文字列のwidthを比較して、ラベルに収まるかどうかの判定を行うことが可能。

参照:UILabelの高さ計算時に気をつけること

しかし、WKInterfaceLabelは下記の理由から、UILabelのように判定を行うことができない。

  • ラベルに表示している文字列を取得するAPIがない
  • ラベルに適用されているUIFontを取得するAPIがない
  • ラベルのframeを取得するAPIがない

回避策として、enumなどを用いて各値を保持しておくという案を思いついたが、ラベルごとに異なるであろう設定をもれなく抜き出し、かつ改修があったときに追随していくことは苦痛に思えたので、「常にスクロールする」仕様とすることが無難だろう。

処理が重く、CPUの使用率に影響がある

当然のことだが、Xcodeでデバッグした限り、スクロールさせるとCPUの使用率があがる。
試しに15個程度のラベルをスクロールさせてみたが、CPU使用率が50%以上という結果になった。
画面外のラベルはスクロールさせないなど、可能な限りスクロールさせないための処理は必須。

WKInterfaceLabelはサブクラスが機能しない

スクロール処理とは関係ない話ではあるが、WKInterfaceLabelはサブクラスが機能しない。

Do not subclass or create instances of this class yourself. Instead, define outlets in your interface controller class and connect them to the corresponding objects in your storyboard file. For example, to refer to a label object in your interface, define a property with the following syntax in your interface controller class:

公式ドキュメントから抜粋。

Xcode上ではなんのサジェストも行われず、上記のドキュメントの記載に気づかずに実装したときの状態を表にした。

やったこと 可否
サブクラス化
Storyboard上のカスタムクラスの設定
ビルド
サブクラス内のメソッドの呼び出し ×

一見サブクラス化できるように思えるが、実際は動かないので、かなしい。

ソースコード&使い方

サンプル動画のInterfaceControllerの実装もあわせて記載。

iOS App同様に、Watch Appがバックグラウンドに移行したときにスクロールを止める処理をお忘れなく。

まとめ

Watch Appはいろいろと制限があって、難しい。
あと情報が少ない上に古いものが多くて、つらい。
みなさんもお持ちの情報で公開できるものがあれば、どんなものでも公開していただけるとお互いに幸せになれそう。