iOS ウィジェットとライブアクティビティの変遷を開発目線で整理する
本記事では、あまり注目されてこなかったかもしれない "ウィジェット / ライブアクティビティ"について、変遷をまとめています。
iOSのウィジェットとライブアクティビティは、ユーザーがアプリケーションの情報を迅速に取得し、インタラクションを行うための重要な要素になり得ます。各所連携して調査した結果、これらの機能は、iOS 8から始まり、iOS 18まで進化してきました。以下では、各バージョンでのウィジェットとライブアクティビティの変遷をまとめます。
WWDC2025で発表される何かによってかき消される可能性もありますが、定点観測という意味で残しておこうと思います。
ウィジェット
iOS 8 (2014): Today View(今⽇の表⽰画⾯) でのウィジェットの導⼊
- フレームワーク→UIKit
- UIViewControllerを使⽤
- サイズが固定、インタラクションは⼤幅に制限
iOS 10 (2016): 機能拡張の導⼊
- ロック画⾯から(今⽇の表⽰画⾯)へのアクセスが可能に
- インタラクション可能なウィジェット(タップ、スワイプでのモード切り替え)
- ウィジェットのサイズ切り替えが可能に(Compactモード、Expandedモードの追加)
iOS 14 (2020): ホーム画⾯でのウィジェットとWidgetKitの導⼊
- フレームワーク→WidgetKit
- WidgetKitの採⽤によりUIKitからSwiftUIへ
- ウィジェットがホーム画⾯に配置可能に
- ⼀部インタラクション可能(タップでアプリを起動のみ)
- ウィジェットのサイズとしてSmall, Medium, Large (iOS 16でExtra Largeが追加)
- データの更新はTimelineProviderによるスナップショット
iOS 16 (2022): インタラクティブ性の向上とロック画⾯ウィジェット
- フレームワーク→WidgetKit
- ロック画⾯にウィジェットが配置可能に
iOS 17 (2023): インタラクティブなウィジェットの導⼊
- フレームワーク→WidgetKit
- ホーム画⾯およびロック画⾯上でいくつかのインタラクションが可能に
- WidgetConfigurationでタップイベントの処理(アプリケーションの特定の機能)の利⽤が可能に
iOS 18 (2024): 機能拡張の導⼊
- システムテーマに応じて動的にデザインが変更(ライト/ダーク、アクセシビリティ)
- ウィジェット間のデータ共有が可能に (AppGroupによる異なるアプリ間での連携)
- SharedContainer(AppGroupの保存領域)とiCloud同期
ウィジェットの変遷まとめ
version | Framework | Lang | feature |
---|---|---|---|
iOS 8~13 | UIKit | Objective-C, Swift | 通知とユーザー操作による更新 |
iOS 14以降 | WidgetKit | SwiftUI | タイムラインによる静的更新を追加 |
iOS 16以降 | WidgetKit | SwiftUI | ロック画面への表示を追加 |
iOS 17以降 | WidgetKit | SwiftUI | UIによるインタラクションを追加 |
ウィジェット 実装⽅法の違い
実装イメージを共有する目的でCodeを掲載しており、動作の保証はしておりません。
UIKitでの実装 (Swift, iOS 8~13)
Template→Today Extension
import UIKit
import NotificationCenter
class MyWidget: UIViewController, NCWidgetProviding {
func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) {
// 更新
completionHandler(.newData)
}
}
WidgetKitでの実装(SwiftUI, iOS 14以降)
Template→Widget Extension
import WidgetKit
import SwiftUI
struct MyWidget: Widget {
var body: some WidgetConfiguration {
StaticConfiguration(kind: "com.example.mywidget", provider: TimelineProvider()) { entry in
. // 更新
WidgetView(entry: entry)
}
.configurationDisplayName("My Widget")
.description("My Widget Description")
}
}
iOS 17でのインタラクションによる更新
Template→Widget Extension
import SwiftUI
import WidgetKit
struct MyWidget: Widget {
var body: some WidgetConfiguration {
StaticConfiguration(kind: "com.example.mywidget", provider: Provider()) { entry in
// ボタンによる更新
Button("Tap Me") {
print("Button tapped!")
}
}
.configurationDisplayName("My Widget")
.description("My Widget Description")
}
}
現在(iOS 17以降)ウィジェットのインタラクションに対応しているUI(SwiftUI)
- Button→AppIntentにて処理を実⾏可能
- Toggle→AppIntentにて処理を実⾏可能
- ContextMenu→メニュー表⽰等
- Link/DeepLink→対応するアプリ内の機能や遷移先への移動等
- ProgressView→プログレスバーの表⽰等
更新間隔
- iOS 14から更新の基準は変わっておらず、基本的にシステム依存(OS依存)
- ユーザーのインタラクションや処理による強制的な更新も最終的にシステム側で制御される
- Appleは5~15分での更新を推奨(?)
擬似リアルタイム更新
- TimelineProviderによる短時間での更新
- 通常の⽅法で単純に更新頻度を上げる
- 分単位での更新が限度
- この場合システム依存度が高く、秒単位ではほぼ実現不可
- UIによる擬似的な更新
- ウィジェット自体の更新ではなく、UIの再描画を利用する
- 単純なもの(テキストレベル)であれば、ある程度は可能
- BGAppRefreshTaskRequestによる擬似的な更新
- 事前にアプリ側でBGTaskSchedulerにてAppGroupのデータを更新
- ウィジェットが表示される際のgetSnapshot、getTimelineのタイミングでデータを読み込む
- 但しウィジェット単体での動作では精度に期待出来ない為プッシュ通知(サイレント)との併用が必要
ライブアクティビティ
iOS 16 (2022): Live Activityの導⼊
- フレームワーク→ActivityKit
- ロック画⾯で、進⾏中のタスクをリアルタイムで表⽰可能
- リアルタイムの情報をDynamic Islandに表⽰(iOS14以降)
iOS 17 (2023): 機能拡張の導⼊
- アクションボタンの導⼊でロック画⾯、Dynamic Island上で直接操作を⾏う事が可能に
- ロック画⾯やDynamic Island上の UIでアニメーション表⽰が可能に
iOS 18 (2024): 機能拡張の導⼊
- ライブアクティビティとウィジェットがデータをシームレスに共有可能に
- データがiCloudを通じて複数のデバイス間で同期可能に
- Dynamic Islandやロック画⾯での表⽰⽅法を調整可能に
基本的なライブアクティビティの仕組み
- 開始→Activityを開始、初回のデータを表⽰
- 更新→サーバーやイベントに基づいてリアルタイムデータをActivityに転送
- 終了→イベントが完了するとActivityが停⽌、削除
ウィジェットとライブアクティビティの違いと関係
概要
ライブアクティビティ | ウィジェット | |
---|---|---|
表示 | ロック画面、Dynamic Island | ホーム画面、ロック画面 |
リアルタイム更新 | サポート(ActivityKit) | 非サポート |
更新方法*1 | Push Notificationsまたはアプリ内からのトリガー | TimelineProviderによるスケジューリング |
インタラクション*2 | タップ、アクションボタン(iOS 17以降) | タップでアプリ起動(iOS 17以降でその他にも対応) |
フレームワーク | ActivityKit | WidgetKit |
※1更新の違い
ライブアクティビティ | ウィジェット | |
---|---|---|
更新の仕組み | アプリ上のイベント、Push通知、リアルタイム処理 | TimelineProviderでスケジュール更新のみ |
更新頻度 | 必要に応じて更新(サーバーまたはアプリでの更新タイミング) | システムが管理(5~15分程度、保証はされない) |
更新データ | アプリまたはサーバーからの動的データ | 事前に用意されたタイムラインエントリ |
プッシュ通知での更新 | プッシュ通知で即時更新 | 無し |
インタラクションによる動作 | 詳細表示 | 無し |
主なユースケース | 配達、タイマー等 | 天気、カレンダー等 |
※2インタラクションの違い
ライブアクティビティ | ウィジェット (iOS 17以降) | |
---|---|---|
基本 | 全体をタップしてアプリを起動可能 | 全体をタップしてアプリを起動可能 |
UI | AppIntentにより処理が可能(ロック画面上でも可) | AppIntentにより処理が可能(ロック画面上では不可) |
基本的な更新 | インタラクションによりリアルタイムに更新 | インタラクションは可能だが静的なスナップショット更新に依存 |
リアルタイムでの更新 | プッシュ通知やバックグラウンドによる更新に対応 | 無し |
若干、名前がThe Other OSにも思えるものが混ざってきているのは感じます。モバイルデバイスが浸透し理想的なUsecaseが具体的になってきたことによって、設計思想が寄せて似てきていると感じます。
まとめ
ウィジェットとライブアクティビティは、iOSの進化に伴い、ユーザー体験を向上させるために重要な要素の一つです。特に、iOS 17以降のインタラクティブなウィジェットやライブアクティビティの導入により、ユーザーはよりリアルタイムで情報を得ることができ、アプリとのインタラクション性が向上しています。
ここでは紹介しませんでしたが、Store上にはややHack的な見え方で、リアルタイム性を実現している例が見られます。有名なアプリというよりは、個人開発者や新興企業でしたので、いつBAN(API非公開化も含む)されても良いようなチャレンジングな枠組みで取り組まれています。
OS提供者視点では基本的にAPIを公開するとサポートが必要になりメリットが少ないですが、ユーザーがついている場合はPlatformの優位性に繋がり情勢も変わるかもしれませんので、チャレンジしていきたいところです。
Discussion