alarmkit

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

AlarmKit

AlarmKit

Schedule prominent alarms and countdown timers that surface on the Lock Screen, Dynamic Island, and Apple Watch. AlarmKit requires iOS 26+ / iPadOS 26+. Alarms override Focus and Silent mode automatically.
AlarmKit builds on Live Activities -- every alarm creates a system-managed Live Activity with templated UI. You configure the presentation via
AlarmAttributes
and
AlarmPresentation
rather than building custom widget views.
See
references/alarmkit-patterns.md
for complete code patterns including authorization, scheduling, countdown timers, snooze handling, and widget setup.
swift
import AlarmKit
在锁屏、灵动岛(Dynamic Island)和Apple Watch上显示醒目的闹钟和倒计时器。AlarmKit要求iOS 26+ / iPadOS 26+系统版本。闹钟会自动覆盖专注模式和静音模式。
AlarmKit 基于Live Activity构建——每个闹钟都会创建一个由系统管理的Live Activity,并使用模板化UI。你可以通过
AlarmAttributes
AlarmPresentation
配置展示效果,无需构建自定义Widget视图。
完整的代码模式(包括授权、调度、倒计时器、贪睡处理和Widget设置)请参考
references/alarmkit-patterns.md
swift
import AlarmKit

Contents

目录

Workflow

工作流程

1. Create a new alarm or timer

1. 创建新闹钟或计时器

  1. Add
    NSAlarmKitUsageDescription
    to Info.plist with a user-facing string.
  2. Request authorization with
    AlarmManager.shared.requestAuthorization()
    .
  3. Configure
    AlarmPresentation
    (alert, countdown, paused states).
  4. Create
    AlarmAttributes
    with the presentation, optional metadata, and tint color.
  5. Build an
    AlarmManager.AlarmConfiguration
    (.alarm or .timer).
  6. Schedule with
    AlarmManager.shared.schedule(id:configuration:)
    .
  7. Observe state changes via
    alarmManager.alarmUpdates
    .
  8. If using countdown, add a widget extension target for non-alerting Live Activity UI.
  1. 在Info.plist中添加
    NSAlarmKitUsageDescription
    字段,并填写面向用户的说明字符串。
  2. 调用
    AlarmManager.shared.requestAuthorization()
    请求授权。
  3. 配置
    AlarmPresentation
    (提醒、倒计时、暂停状态)。
  4. 创建包含展示配置、可选元数据和色调的
    AlarmAttributes
  5. 构建
    AlarmManager.AlarmConfiguration
    (选择
    .alarm
    .timer
    类型)。
  6. 调用
    AlarmManager.shared.schedule(id:configuration:)
    进行调度。
  7. 通过
    alarmManager.alarmUpdates
    监听状态变化。
  8. 如果使用倒计时功能,需添加Widget扩展目标以支持非提醒状态的Live Activity UI。

2. Review existing alarm code

2. 审查现有闹钟代码

Run through the Review Checklist at the end of this document.
按照本文档末尾的检查清单进行审查。

Authorization

授权

AlarmKit requires explicit user authorization. Without it, alarms silently fail to schedule. Request early (e.g., at onboarding) or let AlarmKit prompt automatically on first schedule.
swift
let manager = AlarmManager.shared

// Request authorization explicitly
let state = try await manager.requestAuthorization()
guard state == .authorized else { return }

// Check current state synchronously
let current = manager.authorizationState // .authorized, .denied, .notDetermined

// Observe authorization changes
for await state in manager.authorizationUpdates {
    switch state {
    case .authorized: print("Alarms enabled")
    case .denied:     print("Alarms disabled")
    case .notDetermined: break
    @unknown default: break
    }
}
AlarmKit需要用户明确授权。未授权情况下,闹钟会静默调度失败。建议在应用引导阶段提前请求授权,或让AlarmKit在首次调度时自动提示用户。
swift
let manager = AlarmManager.shared

// 主动请求授权
let state = try await manager.requestAuthorization()
guard state == .authorized else { return }

// 同步检查当前授权状态
let current = manager.authorizationState // .authorized, .denied, .notDetermined

// 监听授权状态变化
for await state in manager.authorizationUpdates {
    switch state {
    case .authorized: print("闹钟功能已启用")
    case .denied:     print("闹钟功能已禁用")
    case .notDetermined: break
    @unknown default: break
    }
}

Alarm vs Timer Decision

闹钟与计时器的选择

FeatureAlarm (
.alarm
)
Timer (
.timer
)
Fires atSpecific time (schedule)After duration elapses
Countdown UIOptionalAlways shown
RecurringYes (weekly days)No
Use caseWake-up, scheduled remindersCooking, workout intervals
Use
.alarm(schedule:...)
when firing at a clock time. Use
.timer(duration:...)
when firing after a duration from now.
特性闹钟(
.alarm
计时器(
.timer
触发时机特定时间(按调度)时长结束后
倒计时UI可选始终显示
重复触发支持(每周重复)不支持
使用场景唤醒闹钟、定时提醒烹饪计时、锻炼间隔
当需要在特定时钟时间触发时,使用
.alarm(schedule:...)
;当需要从当前时间开始计时一段时间后触发时,使用
.timer(duration:...)

Scheduling Alarms

调度闹钟

Alarm.Schedule

Alarm.Schedule

Alarms use
Alarm.Schedule
to define when they fire.
swift
// Fixed: fire at an exact Date (one-time only)
let fixed: Alarm.Schedule = .fixed(myDate)

// Relative one-time: fire at 7:30 AM in device time zone, no repeat
let oneTime: Alarm.Schedule = .relative(.init(
    time: .init(hour: 7, minute: 30),
    repeats: .never
))

// Recurring: fire at 6:00 AM on weekdays
let weekday: Alarm.Schedule = .relative(.init(
    time: .init(hour: 6, minute: 0),
    repeats: .weekly([.monday, .tuesday, .wednesday, .thursday, .friday])
))
闹钟使用
Alarm.Schedule
定义触发时间。
swift
// 固定时间:在指定的Date触发(仅一次)
let fixed: Alarm.Schedule = .fixed(myDate)

// 相对单次触发:在设备时区的早上7:30触发,不重复
let oneTime: Alarm.Schedule = .relative(.init(
    time: .init(hour: 7, minute: 30),
    repeats: .never
))

// 重复触发:工作日早上6:00触发
let weekday: Alarm.Schedule = .relative(.init(
    time: .init(hour: 6, minute: 0),
    repeats: .weekly([.monday, .tuesday, .wednesday, .thursday, .friday])
))

Schedule and Configure

调度与配置

swift
let id = UUID()

let configuration = AlarmManager.AlarmConfiguration.alarm(
    schedule: .relative(.init(
        time: .init(hour: 7, minute: 0),
        repeats: .never
    )),
    attributes: attributes,
    stopIntent: StopAlarmIntent(alarmID: id.uuidString),
    secondaryIntent: SnoozeIntent(alarmID: id.uuidString),
    sound: .default
)

let alarm = try await AlarmManager.shared.schedule(
    id: id,
    configuration: configuration
)
swift
let id = UUID()

let configuration = AlarmManager.AlarmConfiguration.alarm(
    schedule: .relative(.init(
        time: .init(hour: 7, minute: 0),
        repeats: .never
    )),
    attributes: attributes,
    stopIntent: StopAlarmIntent(alarmID: id.uuidString),
    secondaryIntent: SnoozeIntent(alarmID: id.uuidString),
    sound: .default
)

let alarm = try await AlarmManager.shared.schedule(
    id: id,
    configuration: configuration
)

Alarm State Transitions

闹钟状态转换

text
cancel(id:)
    |
scheduled --> countdown --> alerting
    |             |             |
    |         pause(id:)    stop(id:) / countdown(id:)
    |             |
    |         paused ----> countdown (via resume(id:))
    |
cancel(id:) removes from system entirely
  • cancel(id:)
    -- remove the alarm completely (any state)
  • pause(id:)
    -- pause a counting-down alarm
  • resume(id:)
    -- resume a paused alarm
  • stop(id:)
    -- stop an alerting alarm
  • countdown(id:)
    -- restart countdown from alerting state (snooze)
text
cancel(id:)
    |
scheduled --> countdown --> alerting
    |             |             |
    |         pause(id:)    stop(id:) / countdown(id:)
    |             |
    |         paused ----> countdown (via resume(id:))
    |
cancel(id:) removes from system entirely
  • cancel(id:)
    -- 完全移除闹钟(任何状态下均可)
  • pause(id:)
    -- 暂停正在倒计时的闹钟
  • resume(id:)
    -- 恢复暂停的闹钟
  • stop(id:)
    -- 停止正在提醒的闹钟
  • countdown(id:)
    -- 从提醒状态重启倒计时(贪睡)

Countdown Timers

倒计时器

Timers fire after a duration and always show a countdown UI. Use
Alarm.CountdownDuration
to control pre-alert and post-alert durations.
swift
// Simple timer: 5-minute countdown, no snooze
let timerConfig = AlarmManager.AlarmConfiguration.timer(
    duration: 300,
    attributes: attributes,
    stopIntent: StopTimerIntent(timerID: id.uuidString),
    sound: .default
)

let alarm = try await AlarmManager.shared.schedule(
    id: UUID(),
    configuration: timerConfig
)
计时器在时长结束后触发,且始终显示倒计时UI。使用
Alarm.CountdownDuration
控制提醒前和提醒后的时长。
swift
// 简单计时器:5分钟倒计时,无贪睡
let timerConfig = AlarmManager.AlarmConfiguration.timer(
    duration: 300,
    attributes: attributes,
    stopIntent: StopTimerIntent(timerID: id.uuidString),
    sound: .default
)

let alarm = try await AlarmManager.shared.schedule(
    id: UUID(),
    configuration: timerConfig
)

CountdownDuration

CountdownDuration

Alarm.CountdownDuration
controls the visible countdown phases:
  • preAlert
    -- seconds to count down before the alarm fires (the main countdown)
  • postAlert
    -- seconds for a repeat/snooze countdown after the alarm fires
swift
let countdown = Alarm.CountdownDuration(
    preAlert: 600,   // 10-minute countdown before alert
    postAlert: 300   // 5-minute snooze countdown if user taps Repeat
)

let config = AlarmManager.AlarmConfiguration(
    countdownDuration: countdown,
    schedule: .relative(.init(
        time: .init(hour: 8, minute: 0),
        repeats: .never
    )),
    attributes: attributes,
    stopIntent: stopIntent,
    secondaryIntent: snoozeIntent,
    sound: .default
)
Alarm.CountdownDuration
控制可见的倒计时阶段:
  • preAlert
    -- 闹钟触发前的倒计时秒数(主倒计时)
  • postAlert
    -- 闹钟触发后,重复/贪睡的倒计时秒数
swift
let countdown = Alarm.CountdownDuration(
    preAlert: 600,   // 提醒前10分钟倒计时
    postAlert: 300   // 用户点击重复后,5分钟贪睡倒计时
)

let config = AlarmManager.AlarmConfiguration(
    countdownDuration: countdown,
    schedule: .relative(.init(
        time: .init(hour: 8, minute: 0),
        repeats: .never
    )),
    attributes: attributes,
    stopIntent: stopIntent,
    secondaryIntent: snoozeIntent,
    sound: .default
)

Alarm States

闹钟状态

Each
Alarm
has a
state
property reflecting its current lifecycle position.
StateMeaning
.scheduled
Waiting to fire (alarm mode) or waiting to start countdown
.countdown
Actively counting down (timer or pre-alert phase)
.paused
Countdown paused by user or app
.alerting
Alarm is firing -- sound playing, UI prominent
每个
Alarm
都有一个
state
属性,反映其当前生命周期阶段。
状态含义
.scheduled
等待触发(闹钟模式)或等待开始倒计时
.countdown
正在倒计时(计时器或提醒前阶段)
.paused
倒计时被用户或应用暂停
.alerting
闹钟正在提醒——播放声音,UI醒目显示

Observing State Changes

监听状态变化

swift
let manager = AlarmManager.shared

// Get all current alarms
let alarms = manager.alarms

// Observe changes as an async sequence
for await updatedAlarms in manager.alarmUpdates {
    for alarm in updatedAlarms {
        switch alarm.state {
        case .scheduled:  print("\(alarm.id) waiting")
        case .countdown:  print("\(alarm.id) counting down")
        case .paused:     print("\(alarm.id) paused")
        case .alerting:   print("\(alarm.id) alerting!")
        @unknown default: break
        }
    }
}
An alarm that disappears from
alarmUpdates
has been cancelled or fully stopped and is no longer tracked by the system.
swift
let manager = AlarmManager.shared

// 获取所有当前闹钟
let alarms = manager.alarms

// 通过异步序列监听变化
for await updatedAlarms in manager.alarmUpdates {
    for alarm in updatedAlarms {
        switch alarm.state {
        case .scheduled:  print("\(alarm.id) 等待中")
        case .countdown:  print("\(alarm.id) 倒计时中")
        case .paused:     print("\(alarm.id) 已暂停")
        case .alerting:   print("\(alarm.id) 正在提醒!")
        @unknown default: break
        }
    }
}
alarmUpdates
中消失的闹钟表示已被取消或完全停止,不再被系统跟踪。

AlarmAttributes and AlarmPresentation

AlarmAttributes与AlarmPresentation

AlarmAttributes
conforms to
ActivityAttributes
and defines the static data for the alarm's Live Activity. It is generic over a
Metadata
type conforming to
AlarmMetadata
.
AlarmAttributes
遵循
ActivityAttributes
协议,定义闹钟Live Activity的静态数据。它是泛型类型,需搭配遵循
AlarmMetadata
协议的
Metadata
类型使用。

AlarmPresentation

AlarmPresentation

Defines the UI content for each alarm state. The system renders a templated Live Activity using this data -- you do not build custom SwiftUI views for the alarm itself.
swift
// Alert state (required) -- shown when alarm is firing
let alert = AlarmPresentation.Alert(
    title: "Wake Up",
    secondaryButton: AlarmButton(
        text: "Snooze",
        textColor: .white,
        systemImageName: "bell.slash"
    ),
    secondaryButtonBehavior: .countdown  // snooze restarts countdown
)

// Countdown state (optional) -- shown during pre-alert countdown
let countdown = AlarmPresentation.Countdown(
    title: "Morning Alarm",
    pauseButton: AlarmButton(
        text: "Pause",
        textColor: .orange,
        systemImageName: "pause.fill"
    )
)

// Paused state (optional) -- shown when countdown is paused
let paused = AlarmPresentation.Paused(
    title: "Paused",
    resumeButton: AlarmButton(
        text: "Resume",
        textColor: .green,
        systemImageName: "play.fill"
    )
)

let presentation = AlarmPresentation(
    alert: alert,
    countdown: countdown,
    paused: paused
)
定义每个闹钟状态下的UI内容。系统会使用这些数据渲染模板化的Live Activity——你无需为闹钟本身构建自定义SwiftUI视图。
swift
// 提醒状态(必填)——闹钟触发时显示
let alert = AlarmPresentation.Alert(
    title: "起床",
    secondaryButton: AlarmButton(
        text: "贪睡",
        textColor: .white,
        systemImageName: "bell.slash"
    ),
    secondaryButtonBehavior: .countdown  // 贪睡会重启倒计时
)

// 倒计时状态(可选)——提醒前倒计时阶段显示
let countdown = AlarmPresentation.Countdown(
    title: "晨间闹钟",
    pauseButton: AlarmButton(
        text: "暂停",
        textColor: .orange,
        systemImageName: "pause.fill"
    )
)

// 暂停状态(可选)——倒计时暂停时显示
let paused = AlarmPresentation.Paused(
    title: "已暂停",
    resumeButton: AlarmButton(
        text: "恢复",
        textColor: .green,
        systemImageName: "play.fill"
    )
)

let presentation = AlarmPresentation(
    alert: alert,
    countdown: countdown,
    paused: paused
)

AlarmAttributes

AlarmAttributes

swift
struct CookingMetadata: AlarmMetadata {
    var recipeName: String
    var stepNumber: Int
}

let attributes = AlarmAttributes(
    presentation: presentation,
    metadata: CookingMetadata(recipeName: "Pasta", stepNumber: 3),
    tintColor: .blue
)
swift
struct CookingMetadata: AlarmMetadata {
    var recipeName: String
    var stepNumber: Int
}

let attributes = AlarmAttributes(
    presentation: presentation,
    metadata: CookingMetadata(recipeName: "意面", stepNumber: 3),
    tintColor: .blue
)

AlarmPresentationState

AlarmPresentationState

AlarmPresentationState
is the system-managed
ContentState
of the alarm Live Activity. It contains the alarm ID and a
Mode
enum:
  • .alert(Alert)
    -- alarm is firing, includes the scheduled time
  • .countdown(Countdown)
    -- actively counting down, includes fire date and durations
  • .paused(Paused)
    -- countdown paused, includes elapsed and total durations
The widget extension reads
AlarmPresentationState.mode
to decide which UI to render in the Dynamic Island and Lock Screen for non-alerting states.
AlarmPresentationState
是系统管理的闹钟Live Activity的
ContentState
,包含闹钟ID和一个
Mode
枚举:
  • .alert(Alert)
    -- 闹钟正在提醒,包含调度时间
  • .countdown(Countdown)
    -- 正在倒计时,包含触发日期和时长
  • .paused(Paused)
    -- 倒计时已暂停,包含已流逝时长和总时长
Widget扩展通过读取
AlarmPresentationState.mode
来决定在灵动岛和锁屏上为非提醒状态渲染何种UI。

AlarmButton

AlarmButton

AlarmButton
defines the appearance of action buttons in the alarm UI.
swift
let stopButton = AlarmButton(
    text: "Stop",
    textColor: .red,
    systemImageName: "stop.fill"
)

let snoozeButton = AlarmButton(
    text: "Snooze",
    textColor: .white,
    systemImageName: "bell.slash"
)
AlarmButton
定义闹钟UI中操作按钮的外观。
swift
let stopButton = AlarmButton(
    text: "停止",
    textColor: .red,
    systemImageName: "stop.fill"
)

let snoozeButton = AlarmButton(
    text: "贪睡",
    textColor: .white,
    systemImageName: "bell.slash"
)

Secondary Button Behavior

次要按钮行为

The secondary button on the alert UI has two behaviors:
BehaviorEffect
.countdown
Restarts a countdown using
postAlert
duration (snooze)
.custom
Triggers the
secondaryIntent
(e.g., open app)
提醒UI上的次要按钮有两种行为:
行为效果
.countdown
使用
postAlert
时长重启倒计时(贪睡)
.custom
触发
secondaryIntent
(例如打开应用)

Live Activity Integration

Live Activity集成

AlarmKit alarms automatically appear as Live Activities on the Lock Screen and Dynamic Island on iPhone, and in the Smart Stack on Apple Watch. The system manages the alerting UI. For countdown and paused states, add a widget extension that reads
AlarmAttributes
and
AlarmPresentationState
.
A widget extension is required if your alarm uses countdown presentation. Without it, the system may dismiss alarms unexpectedly.
swift
struct AlarmWidgetBundle: WidgetBundle {
    var body: some Widget {
        AlarmActivityWidget()
    }
}

struct AlarmActivityWidget: Widget {
    var body: some WidgetConfiguration {
        ActivityConfiguration(for: AlarmAttributes<CookingMetadata>.self) { context in
            // Lock Screen presentation for countdown/paused states
            AlarmLockScreenView(context: context)
        } dynamicIsland: { context in
            DynamicIsland {
                DynamicIslandExpandedRegion(.center) {
                    Text(context.attributes.presentation.alert.title)
                }
                DynamicIslandExpandedRegion(.bottom) {
                    // Show countdown or paused info based on mode
                    AlarmExpandedView(state: context.state)
                }
            } compactLeading: {
                Image(systemName: "alarm.fill")
            } compactTrailing: {
                AlarmCompactTrailing(state: context.state)
            } minimal: {
                Image(systemName: "alarm.fill")
            }
        }
    }
}
AlarmKit闹钟会自动在iPhone的锁屏和灵动岛、Apple Watch的智能叠放中以Live Activity形式显示。系统管理提醒UI。对于倒计时和暂停状态,需添加Widget扩展来读取
AlarmAttributes
AlarmPresentationState
如果你的闹钟使用倒计时展示,必须添加Widget扩展。否则系统可能会意外取消闹钟。
swift
struct AlarmWidgetBundle: WidgetBundle {
    var body: some Widget {
        AlarmActivityWidget()
    }
}

struct AlarmActivityWidget: Widget {
    var body: some WidgetConfiguration {
        ActivityConfiguration(for: AlarmAttributes<CookingMetadata>.self) { context in
            // 倒计时/暂停状态的锁屏展示
            AlarmLockScreenView(context: context)
        } dynamicIsland: { context in
            DynamicIsland {
                DynamicIslandExpandedRegion(.center) {
                    Text(context.attributes.presentation.alert.title)
                }
                DynamicIslandExpandedRegion(.bottom) {
                    // 根据模式显示倒计时或暂停信息
                    AlarmExpandedView(state: context.state)
                }
            } compactLeading: {
                Image(systemName: "alarm.fill")
            } compactTrailing: {
                AlarmCompactTrailing(state: context.state)
            } minimal: {
                Image(systemName: "alarm.fill")
            }
        }
    }
}

Common Mistakes

常见错误

DON'T: Forget
NSAlarmKitUsageDescription
in Info.plist. DO: Add a descriptive usage string. Without it, AlarmKit cannot schedule alarms at all.
DON'T: Skip authorization and assume alarms will schedule. DO: Call
requestAuthorization()
early and handle
.denied
gracefully.
DON'T: Use
.timer
when you need a recurring schedule. DO: Use
.alarm
with
.weekly([...])
for recurring alarms. Timers are one-shot.
DON'T: Omit the widget extension when using countdown presentation. DO: Add a widget extension target. AlarmKit requires it for countdown/paused Live Activity UI. Why: Without a widget extension, the system may dismiss alarms before they alert.
DON'T: Ignore
alarmUpdates
and track alarm state manually. DO: Observe
alarmManager.alarmUpdates
to stay synchronized with the system. Why: Alarm state can change while your app is backgrounded.
DON'T: Forget to provide a
stopIntent
-- it cannot be nil in practice. DO: Always provide a
LiveActivityIntent
for stop so the button performs cleanup.
DON'T: Store large data in
AlarmMetadata
. It is serialized with the Live Activity. DO: Keep metadata lightweight. Store large data in your app and reference by ID.
DON'T: Use deprecated
stopButton
parameter on
AlarmPresentation.Alert
. DO: Use the current
init(title:secondaryButton:secondaryButtonBehavior:)
initializer.
不要: 忘记在Info.plist中添加
NSAlarmKitUsageDescription
要: 添加描述性的使用说明字符串。没有它,AlarmKit根本无法调度闹钟。
不要: 跳过授权流程,默认认为闹钟会调度成功。 要: 尽早调用
requestAuthorization()
,并在UI中优雅处理
.denied
状态。
不要: 当需要重复调度时使用
.timer
要: 使用
.alarm
搭配
.weekly([...])
实现重复闹钟。计时器仅支持单次触发。
不要: 使用倒计时展示时省略Widget扩展。 要: 添加Widget扩展目标。AlarmKit需要它来支持倒计时/暂停状态的Live Activity UI。 原因: 没有Widget扩展,系统可能在闹钟触发前就将其取消。
不要: 忽略
alarmUpdates
,手动跟踪闹钟状态。 要: 监听
alarmManager.alarmUpdates
以与系统状态保持同步。 原因: 应用在后台时,闹钟状态可能会发生变化。
不要: 忘记提供
stopIntent
——实际上它不能为nil。 要: 始终为停止操作提供
LiveActivityIntent
实现,以便按钮执行清理操作。
不要:
AlarmMetadata
中存储大量数据。它会与Live Activity一起序列化。 要: 保持元数据轻量化。将大量数据存储在应用中,通过ID引用即可。
不要: 使用
AlarmPresentation.Alert
中已弃用的
stopButton
参数。 要: 使用当前的
init(title:secondaryButton:secondaryButtonBehavior:)
初始化方法。

Review Checklist

检查清单

  • NSAlarmKitUsageDescription
    present in Info.plist with non-empty string
  • Authorization requested and
    .denied
    state handled in UI
  • AlarmPresentation
    covers all relevant states (alert, countdown, paused)
  • Widget extension target added if countdown presentation is used
  • AlarmAttributes
    metadata type conforms to
    AlarmMetadata
  • Alarm ID stored for later cancel/pause/resume/stop operations
  • alarmUpdates
    async sequence observed to track state changes
  • stopIntent
    and
    secondaryIntent
    are valid
    LiveActivityIntent
    implementations
  • postAlert
    duration set on
    CountdownDuration
    if snooze (
    .countdown
    behavior) is used
  • Tint color set on
    AlarmAttributes
    to differentiate from other apps
  • Error handling for
    AlarmManager.AlarmError.maximumLimitReached
  • Tested on device (alarm sound/vibration differs from Simulator)
  • Info.plist中存在
    NSAlarmKitUsageDescription
    且字符串非空
  • 已请求授权,并在UI中处理
    .denied
    状态
  • AlarmPresentation
    覆盖了所有相关状态(提醒、倒计时、暂停)
  • 如果使用倒计时展示,已添加Widget扩展目标
  • AlarmAttributes
    的元数据类型遵循
    AlarmMetadata
    协议
  • 已存储闹钟ID,用于后续的取消/暂停/恢复/停止操作
  • 已监听
    alarmUpdates
    异步序列以跟踪状态变化
  • stopIntent
    secondaryIntent
    是有效的
    LiveActivityIntent
    实现
  • 如果使用贪睡(
    .countdown
    行为),已在
    CountdownDuration
    中设置
    postAlert
    时长
  • 已在
    AlarmAttributes
    中设置色调,以与其他应用区分
  • 已处理
    AlarmManager.AlarmError.maximumLimitReached
    错误
  • 已在真机上测试(闹钟声音/振动与模拟器不同)

References

参考资料