ライブアクティビティにインタラクティブな機能を実装する方法
ライブアクティビティにインタラクティブな機能を実装する方法についてまとめる。
iOS 17から、App Intentを使用することで、ライブアクティビティにインタラクティブな機能を実装することができるようになった。
App Intent
App Intentとは
簡単に例えると、App Intent は実行したい処理が記述されている構造体。この構造体で定義されている処理は、アプリを起動せずに実行することができる。
さらにApp Intent は、ライブアクティビティだけではなく、ショートカットやSiri検索でも使用することができる。
一度、App Intentを設計すれば、あらゆる場面で使用することができる。
サンプルコード
struct IncrementIntent: AppIntent {
static var title: LocalizedStringResource = "Increment Count"
func perform() async throws -> some IntentResult {
Counter.incrementCount()
return .result()
}
}
App Intent プロトコルに準拠した構造体を定義する。 perform() 内にインテント実行時に行いたい処理を記述し、返り値は.result() とする。
インテント実行後にダイアログを表示したい時は、.result() の引数でダイアログに表示したい内容を指定することができるが、ライブアクティビティやウィジェットでは、インテント実行後にダイアログを表示することはできない。
ライブアクティビティやウィジェット経由でインテントを実行する時は、title を使用することはないが、App Intent プロトコルに準拠するために定義しておく必要がある。
インタラクティブな機能を実現することができるUI
iOS 17から利用可能な新しいイニシャライザが、Button とToggle に追加された。
イニシャライザの引数に、AppIntent プロトコルに準拠したインスタンスを指定する。生成された各UIパーツにアクションが加わると、初期化時に指定したApp Intentが実行される。
この新しいイニシャライザで各UIパーツのインスタンスを生成することで、ライブアクティビティにインタラクティブな機能を実装することができる。
また、WWDC23で実施されたセッションによると、現時点(2023/11/4)ではインタラクティブな機能を実現するUIパーツはこの2つのみとなっている。
Buttonの実装例
App Intent
struct IncrementIntent: AppIntent {
static var title: LocalizedStringResource = "Increment Count"
func perform() async throws -> some IntentResult {
Counter.incrementCount()
let activity = Activity<CounterAttributes>.activities.first
if let activity {
let updatedState = CounterAttributes.ContentState(
isShow: Counter.currentDisplay(),
count: Counter.currentCount())
Task { @MainActor in
await activity.update(
.init(
state: updatedState,
staleDate: .distantFuture)
)
}
}
return .result()
}
}
View
Button(intent: IncrementIntent()) {
Image(systemName: "plus")
.frame(width: 15, height:15)
}
Toggleの実装例
App Intent
struct DisplayIntent: AppIntent {
static var title: LocalizedStringResource = "Display Count"
func perform() async throws -> some IntentResult {
Counter.toggleDisplay()
let activity = Activity<CounterAttributes>.activities.first
if let activity {
let updatedState = CounterAttributes.ContentState(
isShow: Counter.currentDisplay(),
count: Counter.currentCount())
Task { @MainActor in
await activity.update(
.init(
state: updatedState,
staleDate: .distantFuture)
)
}
}
return .result()
}
}
View
Toggle(isOn: context.state.isShow, intent: DisplayIntent()) {
if context.state.isShow {
Text("Hide")
} else {
Text("Show")
}
}
インタラクティブ処理の流れ
ライブアクティビティでインタラクティブな処理を行う流れは以下のようになる。
Button やToggle がユーザーアクションを検知
初期化時に指定したインテントを実行開始
インテント内でライブアクティビティ更新処理を実施
インテントの実行完了
更新内容に基づいてライブアクティビティの再構成処理を実施
ライブアクティビティの表示が更新される
ここから先は
¥ 200
最後まで記事をお読みいただきありがとうございます! 記事が参考になればフォロー・♥いただけると凄く励みになります🥳