1
0

LiveActivityを導入してNotificationを利用したインタラクティブ性を持たせる part2

Last updated at Posted at 2024-05-31

インテントの作成

まず、インテントを作成していきます。
これはLiveActivityやDynamicIsland内に設置したボタンをタップした際の処理となります。

TestIntent.swift
import AppIntents

@available(iOS 17.0, *)
struct TestIntent: LiveActivityIntent {
	
	public init() {}
	static var title = LocalizedStringResource("Test")
	
	public func perform() async throws -> some IntentResult {
		return .result()
	}
}

このTestIntent内にNotificationCenterの処理を追加していきます。
また、固有のNotification.Nameを使用するためにNotification.Nameの拡張を行なっていきます。
TestIntent.swiftファイル内のコードは以下のようになります。

TestIntent.swift
import AppIntents

@available(iOS 17.0, *)
struct TestIntent: LiveActivityIntent {
	
	public init() {}
	static var title = LocalizedStringResource("Test")
	
	public func perform() async throws -> some IntentResult {
		NotificationCenter.default.post(name: Notification.Name.testNotification, object: self)
		return .result()
	}
}

extension Notification.Name {
	static let testNotification = Notification.Name(rawValue: "TestNotification")
}

DynamicIsland内にボタン設置

次に、先ほど作成したインテントを使用する処理を追加していきます。
DynamicIslandExpandedRegion(.bottom)内に作成しているのですが、それ以外はデフォルトのままです。

LiveActivityTest.swift
struct LiveActivityTest: Widget {
    var body: some WidgetConfiguration {
        ActivityConfiguration(for: LiveActivityAttributes.self) { context in
            // Lock screen/banner UI goes here
            VStack {
                Text("Hello \(context.state.emoji)")
            }
            .activityBackgroundTint(Color.cyan)
            .activitySystemActionForegroundColor(Color.black)

        } dynamicIsland: { context in
            DynamicIsland {
                // Expanded UI goes here.  Compose the expanded UI through
                // various regions, like leading/trailing/center/bottom
                DynamicIslandExpandedRegion(.leading) {
                    Text("Leading")
                }
                DynamicIslandExpandedRegion(.trailing) {
                    Text("Trailing")
                }
                DynamicIslandExpandedRegion(.bottom) {
                    
					HStack {
						Text("Bottom \(context.state.emoji)")
						if #available(iOS 17.0, *) {
							Button(intent: TestIntent()) {
								Text("tap")
							}
						}
					}
                }
            } compactLeading: {
                Text("L")
            } compactTrailing: {
                Text("T \(context.state.emoji)")
            } minimal: {
                Text(context.state.emoji)
            }
            .widgetURL(URL(string: "http://www.apple.com"))
            .keylineTint(Color.red)
        }
    }
}

DynamicIslandExpandedRegion(.bottom)内のボタンにインテントを設定しています。
これをタップすることで先ほど作成したインテントのperform()内の処理が走ります。

アプリ側の処理

アプリ内にDynamicIsland内のボタンをタップした際の処理を追加していきます。
part1で作成したものを使用していきます。

ContentView.swift
import SwiftUI
import ActivityKit

class ContentModel: ObservableObject {
	@Published var test = "1"
	
	init() {
		NotificationCenter.default.addObserver(self, selector: #selector(test2), name: .testNotification, object: nil)
	}
	
	@objc
	func test2(notification: Notification) {
		DispatchQueue.main.async {
			self.test = "2"
		}
		
	}
}

struct ContentView: View {
	@StateObject var model = ContentModel()
    var body: some View {
        VStack {
			Text("Data: \(model.test)")
			Button("開始") {
				let contentState = LiveActivityAttributes.ContentState(emoji: "🍛")
				let attributes = LiveActivityAttributes(contentState: contentState,
														name: "テスト")
				
				do {
					_ = try ActivityKit.Activity<LiveActivityAttributes>.request(attributes: attributes,
																							content: .init(state: contentState,
																										   staleDate: nil), pushType: nil)
				} catch {
					print(error)
				}
			}
        }
    }
}

これにより、DynamicIslandのボタンをタップするとTextが「1」→「2」へとなっていることが確認できます。
ボタンタップ時のNotificationを感知する処理をContentModelに記載してください。
なお、testの値はメインスレッド内で更新するようにしてください。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0