こんにちは。CTO室アプリ統括部でヤフーのアプリの技術的な課題解決や新規技術の検証と開発をしている田中です。iOSアプリ黒帯※1 としても活動しています。
先日開催されたiOSDC Japanで、私はiOSでウィジェットを作成するためのフレームワークである WidgetKit
について発表してきました。その内容についてピックアップして解説しつつ、ヤフーのアプリでどのように利用しているかを紹介します。
※1 黒帯制度とは:各領域において突出した専門性を持つ社員を黒帯として任命し、社内外における活動を会社として支援する制度
iOSDC Japanとは
iOSDC Japanは毎年開催されているiOSの技術カンファレンスです。
ヤフーはダイヤモンドスポンサーとして協賛しています。
今年はヤフーからは2名が登壇しました。
ウィジェット
iOS 14からホーム画面等にウィジェットを設置できるようになりました。
これにより、アプリを直接開かなくてもアプリの情報を素早く確認できるようになりました。
ヤフーではiOS 14の公開に合わせて多くのアプリでウィジェットの機能を提供しています。ぜひお試しください。
ウィジェットは WidgetKit フレームワークを使用して実装します。
ウィジェットの種類
ウィジェットには現時点で4つのサイズ (小、中、大、特大) がありますが、大きさ以外にも2つのタイプがあります。
実は同じウィジェットをホーム画面などに複数設置できるのですが、同じ情報が表示されてもあまりメリットがないですよね。そこで、ウィジェットに個別設定をもたせることで、異なる情報を表示させられます。個別設定が必要かどうかによって、ウィジェットを実装する際に2つの WidgetConfiguration
を使い分けます。
個別設定を持たないシンプルなウィジェットはStaticConfiguration
、個別設定をもつウィジェットはIntentConfiguration
でウィジェットを実装します。
Yahoo!リアルタイム検索アプリにはTwitterで盛り上がっている話題をランキング形式で表示するウィジェットや電車遅延を表示するウィジェットがあります。
前者は全ユーザーに対して同じランキングを表示する仕様で、後者は本体アプリでの設定をApp Groupsで参照する仕様のため、StaticConfiguration
を使っています。
Yahoo!天気アプリではアプリ内で登録した地点の天気情報を表示しています。
複数の地点の天気表示をサポートするため、ウィジェットごとに地点を設定できる IntentConfiguration
を使っています。
ウィジェットの予算
発表では特にウィジェットの更新方法について深掘りしました。
ウィジェットのデータを差し替えるためにはシステムが用意している予算(Budget)が必要です。予算がなくなるとウィジェットがリロードできなくなります。
一日で約40〜70回ほどのリロードができる予算が用意されています。したがって、それを超えないようなアプリの仕様にする必要があります。
また、1回のリロードで複数のEntry
を設定できますが、各Entry
は5分以上の間隔で設定することが推奨されています。
そのため、頻繁な更新は難しいですが、時計やカウントダウンのような時間ベースでの表示更新をしたい場合は、SwiftUIが用意している特別なAPIが利用でき、この方法では予算を使用しません。
Yahoo!乗換案内アプリではこの機能で電車の出発までのカウントダウンを実現しています。
https://blog-transit.yahoo.co.jp/info/20210106_widget.html
ただし時間の表記はSwiftUI側で提供されているスタイルに限定されます。
例えば、時計の場合は「14:00」のような表記となり、「午後2:00」のようなスタイルにはできません。デザイン時にはこの点に気をつけましょう。
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
let date = /* 11月15日 9:41 */
VStack(spacing: 16) {
Text(date, style: .time)
Text(date, style: .date)
Text(date, style: .relative)
Text(date, style: .offset)
Text(date, style: .timer)
Text(date...date.advanced(by: 60 * 60 * 24))
}
.padding()
.previewLayout(.sizeThatFits)
.environment(\.locale, .init(identifier: "ja")) // 言語によっても表記が異なります
}
}
ウィジェットを使ってもらうために
ウィジェットはアプリのようにボタンをタップしたら画面が更新されるというようなインタラクティブな操作はできないため、設置するだけで使えるようなシンプルで分かりやすい機能にする必要があります。
もし、ウィジェットを設置した時に正しく動作せず、正常な表示ができなければ、ユーザーはどうして良いかわからず、ウィジェットを使うことを諦めてしまうかもしれません。
そのため、不具合を起こさないことやユーザーが迷子にならないような案内が非常に重要になります。
前述したウィジェットのリロード頻度に加えて、特にメモリ使用量やエラーハンドリングに注意が必要です。
ウィジェットはメモリ使用量が30MBを超えるとクラッシュしてしまいます。
システムが使用するメモリ使用量はOSによって若干違いがあるため、ある程度余裕のある状態にしておくと安心です。
また、通信結果によってクラッシュしてしまう実装や通信の遅延などによるタイムアウトにも気をつけましょう。
ウィジェットはView
側で非同期に通信をすることはできないため、同期的に画像を取得する実装を見かけますが、通信が遅延した時にクラッシュしてしまう場合があるため、getTimeline
等で取得可能な場合はそこでURLSession
などのタイムアウトを適切に設定できるAPIで通信をするのがおすすめです。
ウィジェットがクラッシュすると真っ黒な表示になり、ユーザーにメッセージを表示することもできなくなってしまいます。
エラーが発生した場合はユーザーにどのようにすれば問題を解消できるのかがわかるメッセージをウィジェット上に表示するのがおすすめです。
さまざまなエラーを一つにまとめて同じエラー表示にしてしまうと、エラーの解消が難しくなってしまうため、エラーの種類ごとに文言は出し分けましょう。
基本的にはウィジェットは設置するだけで使えるのが好ましいですが、事前にアプリで設定が必要な場合もありますよね。
Yahoo!乗換案内のウィジェットでは表示する時刻表が未設定の場合は設定を促す文言を表示し、ウィジェットをタップすると設定画面まで自動で画面遷移する仕様になっています。
このようにアプリ内での設定が必要な場合は設定画面まで導くようにするとユーザーが迷いにくいです。
システムとの連携
最近はアプリからシステムに情報を伝えると、システム側でアプリの情報を活用してくれる連携機能 (Siriショートカットの提案等) が強化されています。
ウィジェットにもその機能があり、活用するとスマートスタックが適切なタイミングでウィジェットの表示を切り替えてくれます。(スマートローテーション)
また、iOS 15にウィジェットの提案という機能が入り、ウィジェットをスマートスタックに設置していなくてもおすすめのウィジェットを表示させられるようになりました。
Yahoo!乗換案内ではこの機能を導入し、アプリをよく使っているユーザーに対して通勤通学のタイミング等で時刻表を表示するようにしています。
詳しくはYahoo!路線情報の公式ブログをご覧ください。
これらの機能によってユーザーが知らなかった機能やアプリの意外な活用方法などを提案でき、エンゲージメント向上につながります。
ただし、これらの提案機能はユーザーにとって見たくない情報が表示されてしまう恐れもあるため、インクルーシブデザインを意識し、機能の使いどころや表示する情報には気をつけましょう。
※提案をオフにする機能や特定のアプリからの提案をオフにする機能はOSによって提供されています。
まとめ
ウィジェットは非常にシンプルが故に意外に実現できない仕様があったり、使用するAPIやその仕様の理解に誤りがあると、WidgetKitの制約によって正常に動作しなくなってしまうことがありますので、気をつけましょう。
より詳しく知りたい方は公開されている発表資料と動画をご覧ください。
アプリで便利な体験を提供するためにはプラットフォームが提供している技術の正しい理解が必要です。
ヤフーではiOSの新機能を積極的にキャッチアップし、早い段階で検証を重ね、いち早く便利な体験を提供すべく開発に取り組んでいます。
ヤフーのアプリのウィジェットをまだ使ってみたことがない方はぜひ触ってみてください。
(この記事に関連する採用情報「アプリ開発エンジニア」もぜひご覧ください)
こちらの記事のご感想を聞かせください。
- 学びがある
- わかりやすい
- 新しい視点
ご感想ありがとうございました