iOS14から登場したウィジェット(WidgetKit)の開発過程で感じた今までのウィジェット(Today Extension)との違い

1. はじめに

こんにちは、UX部モバイルグループにて主にiOS開発を担当している山崎です。

iOS14から今までのウィジェット(以下「Today Extension」と呼びます)に加え、ホーム画面に置ける新しいウィジェット(以下「WidgetKit」と呼びます)が導入されました。

↓ iOS14から登場した新しいウィジェット(WidgetKit)

f:id:cc-yamazaki:20201210175222p:plain



↓ iOS13以前もあった今までのウィジェット


2020年6月にToday Extensionに騰落率順に通貨を並び替えることができる機能を追加し、お陰様で多くのお客様に使っていただくことができました。そこで今回新しく追加したWidgetKitでも騰落率順に通貨を並び替えることができる機能を搭載してリリースいたしました。

TodayExtensionに新機能を追加した際実装を担当しブログを書いたのですが、今回のWidgetKitも私が実装を担当したので、開発の過程で感じたToday ExtensionとWidgetKitの違いについて書いてみます。

tech.coincheck.blog


2. ウィジェットの更新について

Today ExtensionではwidgetPerformUpdate(completionHandler:)という表示内容が更新されるタイミングで呼ばれる関数が用意されています。Apple開発者向けのApp Extension Programming GuideではToday Extensionの更新について以下のように説明されています。
App Extension Programming Guide: Today

To help your widget look up to date, the system occasionally captures snapshots of your widget’s view. When the widget becomes visible again, the most recent snapshot is displayed until the system replaces it with a live version of the view.

システム側で定期的にスナップショットが撮られており、ウィジェットが再び表示されると、システムがウィジェットをライブバージョンのビューに置き換えるまで、最新のスナップショットが表示されると書いてあります。これによりToday Extensionを開いた際、表示されるデータのタイムラグを感じることはあまりないようにできています。

一方WidgetKitではTimelineという概念で更新が行われます。Timelineには表示するデータと表示したい日時が含まれたEntryが詰め込まれ、それぞれのビューはTimelineのEntryにしたがって描画されます。

そのTimelineの要求間隔をgetTimeline(for:in:completion:)で指定できます。それならと毎分更新されるように毎分要求したいところですが、以下のDeveloper Forumsによるとウィジェットの更新数には制限があり最低でも15分の間隔は空ける必要があるようです。ホーム画面でずっと表示されるものなのであまりに短い間隔で更新することはシステム側のリソース的に困難なようです。弊社では15分ごとに更新されるように設定しています。
WidgetKit won't request a new time… | Apple Developer Forums

3. メモリの制限について

以前のブログにてToday Extensionには厳しいメモリ制限があることを書きましたが、WidgetKitでも引き続きメモリ制限があります。

tech.coincheck.blog


以下のDeveloper Forumsでは30MBを超えたところでWidgetKitがシステム側によって強制的に終了させられたようです。Today ExtensionではiPhone8で26MBがMemory Limitだったのでそれほど変わってなさそうです。Today ExtensionはApp Extensionsの一つであり、とにかく軽量ですぐに起動できることが求められていました。WidgetKitでもその位置付けはあまり変わっておらずアプリの情報をホームスクリーン上でさっと確認するための補助的なものなので、相変わらず軽量であることが求められているようです。Today Extensionのとき同様メモリの制限に注意しながら開発する必要があります。
(WidgetKit Memory Leak on Images | Apple Developer Forums)

 

4. 可能なユーザーアクションについて

Today Extensionでは比較的開発の自由度があり、UIKitのUIButtonやUISegmentedControlを置くことができます。(ただしUITextFieldなどのキーボードを含むものなどは置くことができません。App Extension Programming Guideでもnote that iOS widgets don’t support keyboard entry. と明記されています。

そこでToday Extensionの機能を拡充する際はウィジェット上にUISegmentedControlを置き、UISegmentedControlの切り替えによって騰落率順に並び替えることができる機能を実現しました。



しかしWidgetKitではToday Extensionと違いウィジェット上でのアクションがほとんど許されていません。(ただしLinkを使ってタップした際にアプリ上のどこに遷移するかを制御することだけはできます。)UISegmentedControlを置いたところでタップしてもアプリ本体に遷移するだけなので、Today Extensionの時のような方法を使って騰落率順に並び替えできる機能を実現することはできません。WidgetKitにて騰落率順に通貨を並び替えることができる機能を実現するにあたって2つの選択肢を検討しました。

①IntentConfigurationを使って「昇順」「降順」などの選択肢を表示し、ウィジェット内で動的に並び替えができるようにする
②アプリ本体の並び順をWidgetKitでも適用する

①のIntentConfigurationとはこのようにWidgetKitをロングタップした時に現れる「ウィジェットを編集」からウィジェットの設定を動的に変更できる機能です。(画像はWWDCで流れたデモアプリのEmoji Rangersです。)
widget3.001.png
(引用: WWDC20)


IntentConfigurationを使って実装することを最初検討したのですが、お客様に気づいていただけない可能性が高いことから②のアプリ本体の並び順をWidgetKitでも適用する方針を選択しました。この仕様はiPhone標準アプリの株価アプリと近いものになっています。

先日のアップデートにて販売所画面でも騰落率順に通貨を並び替えできるようになったのですが、販売所画面での通貨の並び順をUserDefaultsに保存し、WidgetKitでも販売所画面の並び順が適用されるようにしました。(UserDefaultsのデータをアプリ本体とWidgetKit間で共有するためにはApp Groupsの設定が必要になるのでご注意ください!)

アプリ本体で通貨の並び順などを更新した際は
WidgetCenter.shared.reloadAllTimelines()
を呼んであげる事でWidgetKitでもすぐに並び順が適用されるようにしています。

↓ 先日販売所画面に追加された騰落率順に通貨を並び替えることができる機能です
Image

5. 最後に

今回はToday ExtensionとWidgetKitとの違いについてまとめてみました。

TodayExtensionについてはAppleの開発者向けのドキュメントで既にDeprecatedとなって
Use WidgetKit instead
と強い口調で命令されており、早晩完全になくなりそうです。

↓ Today Extensionのメソッドに関するドキュメントですがDeprecatedになっているのがわかります

f:id:cc-yamazaki:20201202193915p:plain
(引用: Apple Developer Documentation

TodayExtensionの代わりに登場したWidgetKitですが、ウィジェット内でアクションがほとんどできないなど開発の自由度が小さくその点では少し残念な印象を受けました。2020年9月にiOS14がサプライズリリースされてから色々なアプリがWidgetKitに対応しましたが、今後面白いWidgetKitが継続的に生まれるエコシステムを作るためにAppleがWidgetKitの自由度を高めるなどの変更をしてくる可能性もあるのかなと感じました。

これからもウィジェットのみならずユーザーファーストなアプリを提供できるように開発してまいりますので、宜しくお願い致します。

一緒にCoincheckを盛り上げてくれるメンバーを募集しています!

様々なポジションを募集しておりますので、是非ご興味ある方はご応募ください。まずは話を聞いてみたいという方も大歓迎です。