final class AlarmScheduler {
private let manager = AlarmManager.shared
private let holidayProvider = HolidayProvider.shared
...
func cancel(_ alarm: AlarmModel) throws {
try manager.cancel(id: alarm.id)
Task {
await AlarmLiveActivityManager.end(alarmID: alarm.id)
}
}
...
enum AlarmLiveActivityManager {
static func upsert(
alarmID: UUID,
attributes: AlarmAttributes<EmptyMetadata>,
content: ActivityContent<AlarmPresentationState>
) async {
let matches = activeActivities(for: alarmID)
if let activity = matches.first {
await activity.update(content)
await endActivities(matches.dropFirst())
return
}
_ = try? Activity.request(
attributes: attributes,
content: content,
pushType: nil
)
}
static func end(alarmID: UUID) async {
let matches = activeActivities(for: alarmID)
await endActivities(matches)
}
private static func activeActivities(for alarmID: UUID) -> [Activity<
AlarmAttributes<EmptyMetadata>
>] {
Activity<AlarmAttributes<EmptyMetadata>>.activities.filter { activity in
guard isActive(activity.activityState) else { return false }
return activity.content.state.alarmID == alarmID
}
}
private static func endActivities<S: Sequence>(
_ activities: S
) async where S.Element == Activity<AlarmAttributes<EmptyMetadata>> {
for activity in activities {
await activity.end(nil, dismissalPolicy: .immediate)
}
}
private static func isActive(_ state: ActivityState) -> Bool {
switch state {
case .active, .pending, .stale:
return true
case .ended, .dismissed:
return false
@unknown default:
return false
}
}
}
private func endLiveActivity(alarmID: UUID) async {
let activities = Activity<AlarmAttributes<EmptyMetadata>>.activities.filter { activity in
guard isActive(activity.activityState) else { return false }
return activity.content.state.alarmID == alarmID
}
for activity in activities {
await activity.end(nil, dismissalPolicy: .immediate)
}
}
The code is shown above.
During testing, I found the following behavior:
When I swipe the Dynamic Island left or right, the Live Activity disappears and the alarm also stops.
After that, if I open the app and then return to the Home screen, a visual feedback animation appears as if it is entering the Dynamic Island.
In this state, when I long-press the Dynamic Island, it shows an empty, long black Live Activity with no content.
Is there any way to prevent this behavior or properly handle this state so that the empty Live Activity does not appear?