Hello,
I am trying to test a concept of a timer stopwatch with Live Activities and integrating buttons like Pause/Resume. When the stopwatch starts, a new Live Activity is created.
The stopwatch is managed by the ViewModel, which has functions like start(), pause(), resume(), reset(), and also startLiveActivity(), etc.
It uses @AppStorage to store keys like stopWatchModeRaw values, startTimeInterval, etc.
The Live Activity state is stored here in the view model using: private var currentActivity: Activity<StopwatchAttributes>? = nil
The Live Activity is started using:
private func startActivity() async {
guard currentActivity == nil, Activity<StopwatchAttributes>.activities.isEmpty else {
if currentActivity == nil {
findAndAssignExistingActivity()
await updateActivity()
}
return
}
let attributes = StopwatchAttributes()
let state = StopwatchAttributes.ContentState(
.... pass in the content state variables ....
)
let content = ActivityContent(state: state, staleDate: nil)
do {
let activity = try Activity<StopwatchAttributes>.request(
attributes: attributes,
content: content,
pushType: nil
)
// Store the activity instance
self.currentActivity = activity
} catch {
print("Error requesting Live Activity: \(error.localizedDescription)")
}
}
and FindAndAssignExistingAcivity does:
private func findAndAssignExistingActivity() {
if let existingActivity = findActivity(), existingActivity.activityState == .active || existingActivity.activityState == .stale {
print("Found existing activity on launch: \(existingActivity.id)")
self.currentActivity = existingActivity
} else {
print("No existing activity found on launch.")
self.currentActivity = nil
}
}
UpdateActivity if the activity exists with a guard statement, and then update the activity. This is also used when the user taps Pause in the Stopwatch.
The main issue I am facing is with the PauseIntent, it can't find the Live Activity and will always exit at that guard statement.
struct PauseIntent: AppIntent {
static var title: LocalizedStringResource = "Pause Stopwatch"
func perform() async throws -> some IntentResult {
guard let defaults = UserDefaults(suiteName: appGroupID) else {
return .result() // Simple failure
}
let currentModeRaw = defaults.integer(forKey: "stopwatchModeRawValue")
let currentMode = StopwatchMode(rawValue: currentModeRaw) ?? .reset
let startTimeInterval = defaults.double(forKey: "startTimeInterval") // TimeInterval when current running segment started
let accumulatedTime = defaults.double(forKey: "accumulatedTime")
guard let activity = Activity<StopwatchAttributes>.activities.first else {
Self.logger.error("PauseIntent EXIT: No Live Activity found to update. (Activity<StopwatchAttributes>.activities is empty)")
return .result() // EXITING HERE, No Live Activity Found, there was nothing found to update... -> It always exits here
}
followed by rest of the code to update the state of the live activity, but it never executes because the activity = Activity<StopwatchAttributes>.activities.first always returns false.
What seems to be the issue? 1 .Is the method wrong to check for the live activity before attempting to Pause? 2. Can the Live Activity actually Pause the Stopwatch Timer in the main App since the Live Activity is actually a Widget Extension and not the App itself, so it cannot see the data directly?