Apple Watchの最も注目すべき点は、それがユーザーとの関わりを深め、楽しませる新たなチャンスであるということです。iPhoneアプリと比較して、大きな違いは、できるだけ短い時間で行わなければいけないということです - なんと2秒で!2秒で何ができると言うのでしょう!?コンプリケーションや、通知、メモリ上のアプリへのクイックアクセスを用いて、それらの機能をApple Watch上でどのように作成して使うかだけではなく、それぞれのユーザーを楽しませる最善の方法も見ていきます。この try! Swift NYC の講演の後には、すばらしいApple Watchの機能を使って、あなたのアプリがもっと魅力的にする方法を身につけていることでしょう。
イントロダクション (0:00)
私は、watchOS 3 でユーザーエンゲージメントを向上させる話をできることを嬉しく思います。watchOS 3 の話を始める前に、ユーザーエンゲージメント というものが私たちにとって何を意味しているのか、を話したいと思います。普段私たちがユーザー - 彼女を Hectorina と呼びましょう - について考える時、Hectorina が私たちのアプリを使っているときのことを考えると、彼女がiPhoneを使っているところを想像します。そうですよね?そして、彼女は天気をチェックしたり、ニューヨークで最高のイタリアンレストランを見つけたり、Instagramで彼女の友達の写真を見たりできます。さまざまな種類の行動があります。しかし本質的には、すべて結局、彼女はiPhoneと直接インタラクションしています。
でも、彼女がiPhoneを見ていない間のユーザーエンゲージメントはどうでしょう?新しいヘアーカットで彼女自身を飾り立てていたり、明るいダンスフロアで素晴らしいサルサを踊っていたら?波に乗っているかも知れません。そういう場合、彼女はiPhoneに気づかないでしょう。どうやって彼女に気づかせる事ができて、どうしたら彼女がiPhoneに触れていないときでも彼女に必要な情報を伝えることができるでしょうか?
幸いwatchOS 3なら、3つの新しい機能がそれを手助けしてくれます。その新しい機能とは、コンプリケーション 、 バックグラウンドタスク 、ローカル通知 です。
コンプリケーション (2:04)
コンプリケーションはApple Watchの文字盤上のウィジェットで、機械式の時計から借用された言葉です。昔、彼らは時間を知る以外の事を時計の盤面で出来るようにコンプリケーションを作ったのでしょう。そして、それらは作るのがとても困難でした。最も高価なものでは、32もの機械式のコンプリケーションが備わっていたようです。それはアップルによって借用されたクールな言葉です。
watchOS 2の興味深い点は、ほとんどのウォッチフェイスが2つから2つのコンプリケーションのスロットを持っていたことです。ここに見るように、これはウォッチフェイスのモジュールで、およそ5つのスロットを持っています。多くのユーザーは、コンプリケーションの為のスロットをわずか2つから5つに制限されてしまいます。幸運にも、watchOS 3ではそうではなく、異なるウォッチフェイスをスワイプでより簡単に切り替えられるようになりました。これは、ユーザーが制限なくコンプリケーションを持つ事ができることを意味しています。とてもクールでアプリのデベロッパとして非常に有益なことです。
それに伴って、多くのユーザーは恐らくウォッチフェイスに何らかのテーマを設定しているので、これをユーザーが毎日使う訳ではないが場合によっては非常に役に立つテーマのウォッチフェイスを作る手段だと考えることができます。
このスライドは、例えば、ワークアウトをテーマにしたウォッチフェイスを示しています。自分自身のワークアウトに大きく重点を置いていることが分かります。上側の2つのコーナーにワークアウトアプリと心拍数アプリがありますが、これは様々なケースで役に立つでしょう。別の例として、旅行に対してそれを考えることができます。私たちの多くは、飛行機だったり、そのほかの輸送手段でここに来ました。フライトの状態を確認したり、ニューヨークの天気や現地時間を見たり、ウォッチフェイスがとても便利であるところを想像することができます。テーマの決められたウォッチフェイスには、多くの異なる素晴らしい利用法があります。
これに関する他のクールな点は、ただの静的な画像であり左上と右上にそれぞれ存在している2つの異なるコンプリケーションが、2つの異なるアプリへのショートカットである事です。これは、ユーザーが彼らが持っている全てのアプリケーションに素早くアクセスする事を可能にします。コンプリケーションを実装する為に必要な事は、これで全てです。
import ClockKit
class ComplicationController: NSObject, CLKComplicationDataSource {
// MARK: - Timeline Configuration
func getSupportedTimeTravelDirections(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimeTravelDirections) -> Void) {
handler([.forward, .backward])
}
func getTimelineStartDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) {
handler(nil)
}
func getTimelineEndDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) {
handler(nil)
}
func getPrivacyBehavior(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationPrivacyBehavior) -> Void) {
handler(.showOnLockScreen)
}
// MARK: - Timeline Population
func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
// Call the handler with the current timeline entry
handler(nil)
}
func getTimelineEntries(for complication: CLKComplication, before date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) {
// Call the handler with the timeline entries prior to the given date
handler(nil)
}
func getTimelineEntries(for complication: CLKComplication, after date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) {
// Call the handler with the timeline entries after to the given date
handler(nil)
}
// MARK: - Placeholder Templates
func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) {
// This method will be called once per supported complication, and the results will be cached
handler(nil)
}
}
心配いりません、実際には見た目ほど大変な作業ではありません。上半分は主に設定用のコードです。これは、アプリケーションの機能性が変わらない限り、一度設定されて忘れられてしまうものの一つです。心に留めて置きたい主な部分は、ここにある Timeline Population です。少しだけ深入りしてみましょう。
Timeline Populationに関するコードを作る為に、これは基本的に私たちがコンプリケーションで用いるであろうデータのタイムラインを作成できるようにします。タイムラインのコンセプトは、一日を通して表示したい特定の数時間のデータの配列を作るのを可能にする事です。ここにあるのは、一日の中の気温の変化を表示する天気アプリの素晴らしい一例です。これに関する興味深いことは、タイムトラベル という機能も使えるようにすることです。
タイムトラベルは、もし馴染みがないならですが、ユーザーがデジタルクラウンをスクロールさせることで時間を進められるようにし、時間を進めたり戻したりして、未来や過去に起こる事を確認できるようにします。これに関する本当に興味深いことは、それがwatchOS 3の最新のベータ版で、必須ではない なものになったことです。以前は必須でした。また全てのユーザーに対して、実はデフォルトで Off になっていました。アプリケーションのデベロッパとしてクールに感じることは、以下の例で、タイムトラベルもタイムラインも一般的にはサポートする必要が全くないことです。
import ClockKit
class ComplicationController: NSObject, CLKComplicationDataSource {
// MARK: - Timeline Population
func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
// Call the handler with the current timeline entry
handler(nil)
}
func getTimelineEntries(for complication: CLKComplication, before date: Date, limit: Int, withHandler handler: @escaping
([CLKComplicationTimelineEntry]?) -> Void) {
// Call the handler with the timeline entries prior to the given date
handler(nil)
}
func getTimelineEntries(for complication: CLKComplication, after date: Date, limit: Int, withHandler handler: @escaping
([CLKComplicationTimelineEntry]?) -> Void) {
// Call the handler with the timeline entries after to the given date
handler(nil)
}
}
これら3つのデリゲートメソッドをサポートしなければなりませんでしたが、代わりに一つだけメソッドが必要になります。
func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping
(CLKComplicationTimelineEntry?) -> Void) {
// Call the handler with the current timeline entry
handler(nil)
}
私たちが心配していた、大部分がただの設定用だったコンプリケーションについてのブロックを覚えていればですが、これが本当に実装する必要のあるたった一つのメソッドです。
どのようにしてコンプリケーションを作りましょう?はじめに、タイムラインとコンプリケーションの テンプレート を作成しましょう。このようなテンプレートを見てみましょう。テンプレートはウォッチフェイスの異なるスタイルに基づく、ユーザーに情報を表示する為の様々な方法です。
ここに見られるように、小さいモジュール形式のウォッチフェイスやウォッチフェイスの異なるスタイルに依存した様々な種類のコンプリケーションもあります。色々な種類があります。画像とテキストの両方、それらの組み合わせがあります。
このようなモジュール形式の大きなテンプレートを見てみましょう。右側がモジュール形式のウォッチフェイスで、最も大きいコンプリケーションが中央にあります。さらに掘り下げてみると、この大きなコンプリケーションは、上に位置するヘッダーとその下にある2行のテキストからなる3つのテキストを持っています。これがそのテンプレートに必要なすべての実装です。
func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping
(CLKComplicationTimelineEntry?) -> Void) {
// Call the handler with the current timeline entry
let template = CLKComplicationTemplateModularLargeStandardBody()
template.headerTextProvider = CLKSimpleTextProvider(text: “12:00-2:00PM”)
template.body1TextProvider = CLKSimpleTextProvider(text: "Lunch with Lucas")
template.body2TextProvider = CLKSimpleTextProvider(text: "Saru Sushi")
let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
handler(timelineEntry)
}
テンプレートの種類、モジュール形式の大きなテンプレート、さらに下の3行のテキストを指定します。下にあるLucasとのランチをとても簡単に再現することができました。
少しだけ簡略化してみました。おそらくコンプリケーションに動的なコンテンツが欲しいと思うでしょう。でも異なるアプリに対して2つの静的な画像だけを用事できる事を表しているこのスクリーンを覚えていれば、それをコンプリケーションで行うとすると、前に見た静的なテキストの場合と同じくらい簡単に実装することができます。
バックグラウンドタスク (8:42)
バックグラウンドタスクと並んで、Dock と呼ばれる素晴らしくクールな watchOS 3 の機能があります。その機能は、10個のお気に入りのアプリケーション間を前後にスクロールしてそれらをすぐに起動することができます。この機能の他のクールな点は、バックグラウンドタスクを通じて、ユーザーがそれらのアプリケーションをスクロールしている間それらをタップしなくてもバックグラウンドでアップデートでき、何もしなくても最新のアップデートと通知を受け取ることができます。どんな種類のバックグラウンドタスクがあるか見てみましょう。
基本的なアプリケーションを更新するバックグラウンドタスクやスナップショット更新、URLSession
、Watch Connectivityもあります。アプリケーションの更新と共に、これが初めにやらないといけないことです。普通、他のタスクを誘発させるためにバックグラウンドタスクを実行します。ここから、スナップショットを起動することも、バックグラウンドでNSURLSession
を使って情報を取得することもできます。
スナップショット更新を見ましょう。この機能によってアプリケーションのUIを更新したり、ビューコントローラをプッシュ、ポップ、プレゼントすることができます。これは、バックグラウンドでUI要素とやり取りをしてユーザーに最新の画面をすぐに提供することができる本当にクールな機能です。
URLSession
は通常のiOS開発で使うバックグラウンドURLSession
タスクとよく似ています。ここで、NSURLSession
を起動してサーバーに出て、ユーザーに見せたい情報を更新することができます。
最後に、他にも劣らず重要なのですが、Watch Connectivityがあります。この機能に精通していない方の為に説明しますと、Watch ConnectivityはBluetooth通信によってウォッチと電話との間でデータの通信を行う手段です。
なぜNSURLSession
が既にあるのにバックグラウンドタスクが必要なのか、不思議に思われるかもしれません。なぜその上でこれを行う必要があるのでしょう?もし私たちがよい開発者でありよい市民でありたいと思っていて、両デバイス間で同じデータを使っているなら、私達はユーザーが無制限にデータを扱えず帯域幅がとても重要な事を知っていますから、サーバーから確実に一度だけデータを取得してそれを両デバイス間で共有したいと思うでしょう。ですから、バックグラウンドタスクをユーザーに提供するときはこれらのことを念頭においてください。
ローカル通知 (11:35)
ローカル通知はプッシュ通知と非常に似ていますが、それらはウォッチ上で設定され、新しいクールな通知センターによってハンドリングされ、両デバイスに同じ通知を送信することもできます。
// Create the content
let content = UNMutableNotificationContent()
content.title = NSString.localizedUserNotificationString(forKey: "Hello!", arguments: nil)
content.body = NSString.localizedUserNotificationString(forKey: "Hello_message_body", arguments: nil)
content.sound = UNNotificationSound.default()
// Deliver the notification in five seconds.
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 5, repeats: false)
let request = UNNotificationRequest.init(identifier: "FiveSecond", content: content, trigger:trigger)
// Schedule the notification.
let center = UNUserNotificationCenter.current()
center.add(request)
これが通知を設定する方法です。まず、コンテンツを作ります。コンテンツを作成し、タイトルとボディ、それと音をセットし、これを通知と紐づけます。そこから、どれだけ時間が経ったら通知を発行するかを設定します。約5秒後に設定してあることが分かるかと思います。最後に、新しい通知センターに通知を設定し、適切な時間に発行されるようにします。
ローカル通知について補足したいもう一つの点は、それが通知にカスタムなレスポンスを設定できるとてもクールな機能であることです。アプリケーションを起動することなくユーザーエンゲージメントを促すもう一つの方法は、通知を介して、ウォッチ上で何らかのタスクを完了させることです。タスクをスヌーズするか完了させるToDoアプリがあります。これをどのように行うかを見てみましょう。
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
if response.actionIdentifier == "Complete" {
//Handle response here
}
}
まず、userNotificationCenter
didReceive response
関数でハンドリングを行います。ここで行う全ての事はレスポンスを受け取ることで、アクションの識別子を確認し、目的のものと一致したら適切な処理を行います。
結論 (13:53)
以上です。要点は、ユーザーが自ら何かをすることなく、アプリケーションを不可欠なものにする為に、コンプリケーションやバックグラウンドタスク、ローカル通知を用いることができるという事です。これの本当に重要なことは、ユーザーが何もすることなく利益を得ることができるので、アプリケーションにこれらの付加的なものを補う素晴らしい方法であるということです。
今やあなたのアプリケーションは、クールなものの一つから、ユーザーにとって絶対に欠かせないものになります。もし watchOS 3 についてさらに知りたい場合は、WWDC ‘16からいつくかの要点についてブログを書いたので、それらを読むことを強くお勧めします。いくつか本当にクールな手書きのノートも載せているので、もし視覚的な方が理解しやすいという方はぜひ利用してください。ありがとうございました。
参考資料
About the content
2016年9月のtry! Swift NYCの講演です。映像はRealmによって撮影・録音され、主催者の許可を得て公開しています。