3.4K Views
October 31, 22
スライド概要
Live Activityを さわってみた 2022.10.31 potatotips #79 itok@そらかぜ
itok@そらかぜ • • いとうけい(itok) の中の人 • モバイルアプリエンジニア 兼 CEO • 副業でフリーランス的 • https://itok.jp/, https://sorakaze.co.jp/, @itokjp
所在地:京都市中京区 社員1人=自分
実績 自社 受託
iOS / Android / macOS / Windows / サーバ 一人でやってます(デザイン以外)
Live Activity
Live Activity • WidgetKitとActivityKitをもちいて実現 dynamic island lock screen
参考情報 ActivityKit • Displaying live data with Live Activities • • https://developer.apple.com/documentation/activitykit/displaying-live-data-withlive-activities Updating and ending your Live Activity with remote push noti cations • https://developer.apple.com/documentation/activitykit/update-and-end-yourlive-activity-with-remote-push-noti cations fi • https://developer.apple.com/documentation/activitykit fi •
制限事項 • iPhone(iOS 16.1以降)でのみ有効(Xcode 14.1) • • • dynamic islandは iPhone 14 Proのみ 明示的に終了しない場合は8時間持続 • dynamic islandは8時間後に消える • lock screenはユーザが消さない限りさらに4時間表示 ネットワークや位置情報へのアクセスはできない • データの更新はアプリ本体 or リモート通知から
dynamic island compact 通常 両サイド別々に定義 minimal 複数のwidgetが共存 systemが優先度決定 expanded UIパーツも配置可 全てを定義する必要あり
static / dynamic data ActivityAttributes staticなデータ ContentState dynamicなデータ struct MyWidgetAttributes: ActivityAttributes { public struct ContentState: Codable, Hashable { var value: Int } var name: String }
Widget Extension Widget Extensionとして追加
WidgetKit struct MyWidgetLiveActivity: Widget { var body: some WidgetConfiguration { ActivityConfiguration(for: MyWidgetAttributes.self) { context in // Lock screen LockScreenView(context: context) } dynamicIsland: { context in // Dynamic island DynamicIsland { ... } } } }
WidgetKit
struct LockScreenView: View {
let context: ActivityViewContext<MyWidgetAttributes>
var body: some View {
VStack {
Text("Hello \(context.state.value)")
}
}
}
WidgetKit DynamicIsland { // Expanded DynamicIslandExpandedRegion(.leading) { } DynamicIslandExpandedRegion(.trailing) { } DynamicIslandExpandedRegion(.bottom) { } DynamicIslandExpandedRegion(.center) { } } compactLeading: { // Compact } compactTrailing: { // Compact } minimal: { // Minimal }
アプリ側の設定 NSSupportsLiveActivities = YES
アプリからの制御 • 開始(foregroundからのみ) let attributes = MyWidgetAttributes(name: "test") let contentState = MyWidgetAttributes.ContentState(value: value) do { activity = try Activity.request(attributes: attributes, contentState: contentState) } catch { } • 更新(background可) let contentState = MyWidgetAttributes.ContentState(value: value) await activity?.update(using: contentState) • 終了(background可) let lastState = MyWidgetAttributes.ContentState(value: value) await activity?.end(using: lastState, dismissalPolicy: .default)
リモート通知による更新 • ContentStateと同じ構造をpushすることで更新 • 1時間に数回は送れる(ほどほどに) • 通知オフの場合もあるのでアプリからの更新は必要
Live Activityで 新しいユーザ体験を