watchOS2の新しい機能であるcomplicationについてまとめました。
なお、ここで書いている内容はデベロッパープログラムに登録していなくても閲覧可能なドキュメント、WWDCのセッションを元に書いています。また、画像はすべてセッションのPDFのものを使用しています。
complication
complicationはwatchOS2で追加された機能で、Apple Watchのフェイスにアプリのデータを表示できるようにする機能です。
watchOS2からTime Travelという機能が追加され、時系列ごとの情報の表示もできます。また、complicationの表示領域をタップするとWatch appへと遷移するようになっています。
参考資料
watchOS 2 Transition GuideとCreating Complications with ClockKitを参考にしました。
Complication Families
complicationの表示のタイプは大きく分けると5つになります。
モジュラーで表示されるModular SmallとModular Large
Modular large
Modular largeはcomplicationの中でも最大の表示領域を持っています。開発者側からするとこれを使ってほしいですね 笑
Modular small
モジュラーにはModular smallも用意されています。こちらはあまり情報の表示ができません
ユーティリティで表示できるUtilitarian smallとUtilitarian large
Utilitarian small
ユーティリティで表示できるUtilitarian smallは少し長めの文字を表示できるようになっています(長めといってもApple Watchの画面なのでそこまで多くは表示できません)。
Utilitarian large
Utilitarian largeはUtilitarian smallを横に長くしたものです。
丸い時計盤で表示されるCircular small
Circular Small
最後にCircular smallです。丸い時計盤の四隅に表示されます。非常に小さな情報しか表示できません。
注意
なお、Complication Familiesすべてをサポートする必要はありません。 自分のアプリに必要な形式だけをサポートするようにすればOKです。
Complication Template
Complication Familyそれぞれにいくつかのテンプレートが用意されています。
Utilitarian largeについては一種類しかありませんが、ほかのcomplicationは複数のレイアウトが用意されています。
これらのレイアウトのためにCLKComplicationTemplateクラスを継承したクラスがたくさん用意されています。いまのところ22クラスありました。
CLKTextProvider
, CLKImageProvider
CLKComplicationTemplateを継承したクラスに画像とかテキストデータを入れる場合はCLKTextProviderとかCLKImageProviderに入れる必要があります。
CLKCompliationTemplate
を継承したクラスを作成し、そのクラスが持っているプロパティに必要なデータを入れることでcompliationの表示を行います。
この際、画像やテキストを入れることになりますがNSString
やUIImage
を直接使うのではなく、CLKTextProvider
, CLKImageProvider
に変換する必要があります。
例えば、Modular largeのテンプレートを作成する際は以下のようになります。
let modularLage = CLKComplicationTemplateModularLargeStandardBody()
modularLage.headerTextProvider = CLKSimpleTextProvider(text: "Long Text")
modularLage.body1TextProvider = CLKSimpleTextProvider(text: "Body Text 1")
modularLage.body2TextProvider = CLKSimpleTextProvider(text: "Body Text 2")
modularLage.headerImageProvider = CLKImageProvider(backgroundImage: UIImage(named: "image"), backgroundColor: nil)
CLKComplicationDataSource
complicationでデータを表示するにはCLKComplicationDataSource
プロトコルに適合したクラスを作ってデータを返す必要があります。このクラスは、watchOS2のターゲットを作成する際に、complicationに対応するかのチェックを入れれば、自動的に作成されます。
class ComplicationController: NSObject, CLKComplicationDataSource {
// 中略
}
このクラスの役割は、データをcomplicationで表示するのに適した形に変更することです。
getSupportedTimeTravelDirectionsForComplication:withHandler
このメソッドの役割はTimeTravelで未来のデータをサポートするか、過去のデータをサポートするかなどを決めることです。
Time Travelで過去のデータの表示、未来のデータの表示をサポートする場合は以下のように書きます。
func getSupportedTimeTravelDirectionsForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimeTravelDirections) -> Void) {
handler([CLKComplicationTimeTravelDirections.Forward, CLKComplicationTimeTravelDirections.Backward])
}
逆にTime Travelをサポートしないようにするには以下のように書きます。
func getSupportedTimeTravelDirectionsForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimeTravelDirections) -> Void) {
handler(CLKComplicationTimeTravelDirections.None)
}
getTimelineStartDateForComplication:withHandler:とgetTimelineEndDateForComplication:withHandler:でTimeTravel
この2つのメソッドはTimeTravelで表示サポートする時間帯を決めるために使用します。
以下のコードは現在の時間から前後12時間をTime Travelでサポートする際のコードです。
func getTimelineStartDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
let time = NSDate(timeIntervalSinceNow: NSTimeInterval(-60*60*12))
handler(time)
}
func getTimelineEndDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
let time = NSDate(timeIntervalSinceNow: NSTimeInterval(60*60*12))
handler(time)
}
デジタルクラウンで範囲外の時間になった場合はcomplicationの表示が暗転します。
getPrivacyBehaviorForComplication:withHandler:
プライバシー的に表示したくないデータの場合がある場合に表示します。
プライバシーを考慮しなくても良いデータであれば以下のように。
func getPrivacyBehaviorForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationPrivacyBehavior) -> Void) {
handler(CLKComplicationPrivacyBehavior.ShowOnLockScreen)
}
プライバシーを考慮すべきデータであれば以下のように設定します。
func getPrivacyBehaviorForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationPrivacyBehavior) -> Void) {
handler(CLKComplicationPrivacyBehavior.HideOnLockScreen)
}
getCurrentTimelineEntryForComplication:withHandler
, getTimelineEntriesForComplication:beforeDate:limit:withHandler:
,getTimelineEntriesForComplication:afterDate:limit:withHandler:
これらのメソッドを使用して、時間ごとの表示するデータを返します。complicationに表示するデータはこの3つのメソッドを使って用意します。
現在の時間データを返す場合のサンプルコードです。
func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: ((CLKComplicationTimelineEntry?) -> Void)) {
var entry : CLKComplicationTimelineEntry?
let now = NSDate()
switch complication.family {
case .ModularSmall:
let textTemplate = CLKComplicationTemplateModularSmallSimpleText()
textTemplate.textProvider = CLKSimpleTextProvider(text: "Long Text")
entry = CLKComplicationTimelineEntry(date: now, complicationTemplate: textTemplate)
handler(entry)
}
handler(nil)
}
getPlaceholderTemplateForComplication:withHandler
complication設定時に表示されるデータはgetPlaceholderTemplateForComplication:withHandler
を使って設定します。
注意点
watchOS 2 Transition Guideには以下のようなことが書かれていました。
- データソースのメソッドは最小限にとどめておくこと
- 通信してデータを取ってくるとか計算とかデータの転送が遅れるようなことはしない
- データの取得や計算が必要な場合はiOSアプリ側で行ったり、WatchKit extensionの別の場所で行い、それをcomplicationからアクセス可能な場所にキャッシュさせて使用すること
- データソースのメソッドではキャッシュしたデータを取ってきて、ClockKitの要求するフォーマットに設定するだけにする
要するに データソースは基本的にキャッシュさせたデータを読み込ませるように設計しよう ということですね。
まとめ
最初は微妙な機能かなと思っていたのですが、ちゃんと調べたり検証したりしているうちに色々と使いどころのある機能だなと感じました。
ただし表示できる情報の量に制限があり、表示するデータに時間の情報が必要なのでアプリの機能次第なのかなとも感じました。
ただ、Apple Watchで一番使用する機能は 時計 だと思うので、そこにデータを表示できるのはかなり強みだと感じています。