axiom-alarmkit-ref
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAlarmKit Reference
AlarmKit 参考文档
Complete API reference for AlarmKit, Apple's framework for scheduling alarms and countdown timers with system-level alerting, Dynamic Island integration, and focus/silent mode override.
Apple官方AlarmKit框架的完整API参考,该框架用于设置闹钟和倒计时计时器,支持系统级提醒、Dynamic Island集成,以及绕过专注/静音模式。
Overview
概述
AlarmKit lets apps create alarms and timers that behave like the built-in Clock app -- they override Do Not Disturb, appear in the Dynamic Island, and show on the Lock Screen. The framework handles scheduling, snooze, pause/resume, and UI presentation through a small set of types centered on .
AlarmManagerAlarmKit允许应用创建与系统自带“时钟”App行为一致的闹钟和计时器——它们可以绕过“请勿打扰”模式、显示在Dynamic Island中,还能在锁屏界面展示。该框架通过以为核心的少量类型,处理调度、贪睡、暂停/恢复以及UI展示等操作。
AlarmManagerSystem Requirements
系统要求
- iOS 26+ (AlarmKit introduced in iOS 26)
- Widget Extension required for Live Activity / Dynamic Island presentation
- Physical device recommended for alarm sound and notification testing
- iOS 26+(AlarmKit在iOS 26中首次推出)
- Widget Extension:实现Live Activity / Dynamic Island展示的必要组件
- 物理设备:推荐用于测试闹钟声音和通知
Part 1: Key Components
第一部分:核心组件
AlarmManager
AlarmManager
Singleton entry point for all alarm operations.
swift
import AlarmKit
let manager = AlarmManager.sharedAll scheduling, cancellation, and observation flows through this shared instance.
所有闹钟操作的单例入口。
swift
import AlarmKit
let manager = AlarmManager.shared所有调度、取消和监听流程都通过这个共享实例完成。
Alarm
Alarm
Describes an alarm that can alert once or on a repeating schedule.
swift
struct Alarm {
var id: UUID
var schedule: Schedule?
var countdownDuration: CountdownDuration?
var state: AlarmState
}描述可单次触发或重复触发的闹钟。
swift
struct Alarm {
var id: UUID
var schedule: Schedule?
var countdownDuration: CountdownDuration?
var state: AlarmState
}AlarmPresentation
AlarmPresentation
Content for the alarm UI across three states -- alerting, counting down, and paused.
swift
struct AlarmPresentation {
var alert: Alert // Required: shown when alarm fires
var countdown: Countdown? // Optional: shown during countdown
var paused: Paused? // Optional: shown when paused
}闹钟在三种状态下的UI内容——触发提醒、倒计时中、已暂停。
swift
struct AlarmPresentation {
var alert: Alert // 必填:闹钟触发时显示
var countdown: Countdown? // 可选:倒计时过程中显示
var paused: Paused? // 可选:暂停时显示
}AlarmAttributes
AlarmAttributes
Generic container pairing presentation with app-specific metadata and tint color. Used to configure the Live Activity widget.
swift
struct AlarmAttributes<Metadata: AlarmMetadata> {
var presentation: AlarmPresentation
var metadata: Metadata
var tintColor: Color
}通用容器,用于关联展示内容、应用专属元数据和色调,配置Live Activity小组件时会用到。
swift
struct AlarmAttributes<Metadata: AlarmMetadata> {
var presentation: AlarmPresentation
var metadata: Metadata
var tintColor: Color
}AlarmMetadata
AlarmMetadata
Protocol for app-specific data attached to an alarm. Conform an empty struct for minimal usage, or add properties for richer UI.
swift
struct RecipeMetadata: AlarmMetadata {
let recipeName: String
let cookingStep: String
}用于附加到闹钟的应用专属数据协议。可遵循空结构体实现基础用法,或添加属性以实现更丰富的UI。
swift
struct RecipeMetadata: AlarmMetadata {
let recipeName: String
let cookingStep: String
}Part 2: Authorization
第二部分:授权
Apps must request permission before scheduling alarms. Add to Info.plist.
NSAlarmKitUsageDescription应用在设置闹钟前必须请求权限。需在Info.plist中添加字段。
NSAlarmKitUsageDescriptionRequesting Authorization
请求授权
swift
func requestAlarmAuthorization() async -> Bool {
do {
let state = try await AlarmManager.shared.requestAuthorization()
return state == .authorized
} catch {
print("Authorization error: \(error)")
return false
}
}swift
func requestAlarmAuthorization() async -> Bool {
do {
let state = try await AlarmManager.shared.requestAuthorization()
return state == .authorized
} catch {
print("Authorization error: \(error)")
return false
}
}Checking Current State
检查当前状态
Use (not ) to read the current value:
authorizationStateauthorizationStatusswift
let state = await AlarmManager.shared.authorizationState
// .authorized | .denied | .notDetermined使用(而非)读取当前权限状态:
authorizationStateauthorizationStatusswift
let state = await AlarmManager.shared.authorizationState
// .authorized | .denied | .notDeterminedObserving Authorization Changes
监听授权状态变化
swift
for await authState in AlarmManager.shared.authorizationUpdates {
switch authState {
case .authorized: enableAlarmUI()
case .denied: showPermissionPrompt()
case .notDetermined: break
@unknown default: break
}
}swift
for await authState in AlarmManager.shared.authorizationUpdates {
switch authState {
case .authorized: enableAlarmUI()
case .denied: showPermissionPrompt()
case .notDetermined: break
@unknown default: break
}
}Part 3: Scheduling Alarms
第三部分:设置闹钟
Every alarm requires a , an , and a call to .
UUIDAlarmManager.AlarmConfigurationschedule(id:configuration:)每个闹钟都需要一个、一个,并调用方法。
UUIDAlarmManager.AlarmConfigurationschedule(id:configuration:)One-Time Alarm
单次闹钟
swift
let id = UUID()
let time = Alarm.Schedule.Relative.Time(hour: 7, minute: 30)
let schedule = Alarm.Schedule.relative(.init(
time: time,
repeats: .never
))
let alert = AlarmPresentation.Alert(
title: "Wake Up",
stopButton: .stopButton,
secondaryButton: .snoozeButton,
secondaryButtonBehavior: .countdown
)
struct EmptyMetadata: AlarmMetadata {}
let config = AlarmManager.AlarmConfiguration(
countdownDuration: nil,
schedule: schedule,
attributes: AlarmAttributes(
presentation: AlarmPresentation(alert: alert),
metadata: EmptyMetadata(),
tintColor: .blue
),
sound: .default
)
let alarm = try await AlarmManager.shared.schedule(id: id, configuration: config)swift
let id = UUID()
let time = Alarm.Schedule.Relative.Time(hour: 7, minute: 30)
let schedule = Alarm.Schedule.relative(.init(
time: time,
repeats: .never
))
let alert = AlarmPresentation.Alert(
title: "Wake Up",
stopButton: .stopButton,
secondaryButton: .snoozeButton,
secondaryButtonBehavior: .countdown
)
struct EmptyMetadata: AlarmMetadata {}
let config = AlarmManager.AlarmConfiguration(
countdownDuration: nil,
schedule: schedule,
attributes: AlarmAttributes(
presentation: AlarmPresentation(alert: alert),
metadata: EmptyMetadata(),
tintColor: .blue
),
sound: .default
)
let alarm = try await AlarmManager.shared.schedule(id: id, configuration: config)Repeating Alarm
重复闹钟
Use for specific days:
.weekly(Array(weekdays))swift
let time = Alarm.Schedule.Relative.Time(hour: 6, minute: 0)
let schedule = Alarm.Schedule.relative(.init(
time: time,
repeats: .weekly([.monday, .tuesday, .wednesday, .thursday, .friday])
))使用指定重复的日期:
.weekly(Array(weekdays))swift
let time = Alarm.Schedule.Relative.Time(hour: 6, minute: 0)
let schedule = Alarm.Schedule.relative(.init(
time: time,
repeats: .weekly([.monday, .tuesday, .wednesday, .thursday, .friday])
))Countdown Timer
倒计时计时器
Set and provide with a interval:
schedule: nilcountdownDurationpreAlertswift
let countdown = Alarm.CountdownDuration(
preAlert: 300, // 5 minutes
postAlert: 10 // Optional post-alert snooze window
)
let config = AlarmManager.AlarmConfiguration(
countdownDuration: countdown,
schedule: nil,
attributes: attributes,
sound: .default
)Timers support pause/resume and show a countdown presentation when is provided.
AlarmPresentation.countdown设置并提供带有时间间隔的:
schedule: nilpreAlertcountdownDurationswift
let countdown = Alarm.CountdownDuration(
preAlert: 300, // 5分钟
postAlert: 10 // 可选的提醒后贪睡窗口
)
let config = AlarmManager.AlarmConfiguration(
countdownDuration: countdown,
schedule: nil,
attributes: attributes,
sound: .default
)计时器支持暂停/恢复,当提供时会显示倒计时界面。
AlarmPresentation.countdownSnooze Configuration
贪睡配置
Snooze uses combined with a secondary action:
CountdownDuration.postAlert.snoozeButtonswift
let alert = AlarmPresentation.Alert(
title: "Alarm",
stopButton: .stopButton,
secondaryButton: .snoozeButton,
secondaryButtonBehavior: .countdown // Starts post-alert countdown
)
let countdownDuration = Alarm.CountdownDuration(
preAlert: nil,
postAlert: 9 * 60 // 9-minute snooze
)贪睡功能结合和次要操作实现:
CountdownDuration.postAlert.snoozeButtonswift
let alert = AlarmPresentation.Alert(
title: "Alarm",
stopButton: .stopButton,
secondaryButton: .snoozeButton,
secondaryButtonBehavior: .countdown // 启动提醒后倒计时
)
let countdownDuration = Alarm.CountdownDuration(
preAlert: nil,
postAlert: 9 * 60 // 9分钟贪睡
)Part 4: Customizing Alarm UI
第四部分:自定义闹钟UI
Alert Presentation
提醒界面
The alert state is shown when the alarm fires. The stop button is required; secondary button is optional.
swift
// Minimal
let basic = AlarmPresentation.Alert(
title: "Alarm",
stopButton: .stopButton
)
// With custom button labels
let custom = AlarmPresentation.Alert(
title: "Medication Reminder",
stopButton: AlarmButton(label: "Taken"),
secondaryButton: AlarmButton(label: "Remind Later"),
secondaryButtonBehavior: .countdown
)
// With open-app action
let openApp = AlarmPresentation.Alert(
title: "Workout Time",
stopButton: .stopButton,
secondaryButton: .openAppButton,
secondaryButtonBehavior: .custom
)闹钟触发时显示提醒状态。停止按钮为必填项,次要按钮为可选。
swift
// 基础版
let basic = AlarmPresentation.Alert(
title: "Alarm",
stopButton: .stopButton
)
// 自定义按钮标签
let custom = AlarmPresentation.Alert(
title: "Medication Reminder",
stopButton: AlarmButton(label: "Taken"),
secondaryButton: AlarmButton(label: "Remind Later"),
secondaryButtonBehavior: .countdown
)
// 带打开应用操作
let openApp = AlarmPresentation.Alert(
title: "Workout Time",
stopButton: .stopButton,
secondaryButton: .openAppButton,
secondaryButtonBehavior: .custom
)Countdown Presentation
倒计时界面
Shown while a timer counts down. Only relevant for alarms with .
countdownDuration.preAlertswift
let countdown = AlarmPresentation.Countdown(
title: "Timer Running",
pauseButton: .pauseButton
)计时器倒计时过程中显示。仅对带有的闹钟有效。
countdownDuration.preAlertswift
let countdown = AlarmPresentation.Countdown(
title: "Timer Running",
pauseButton: .pauseButton
)Paused Presentation
暂停界面
Shown when a countdown timer is paused.
swift
let paused = AlarmPresentation.Paused(
title: "Timer Paused",
resumeButton: .resumeButton
)倒计时计时器暂停时显示。
swift
let paused = AlarmPresentation.Paused(
title: "Timer Paused",
resumeButton: .resumeButton
)Full Three-State Presentation
完整三状态界面
Combine all three for a complete timer experience:
swift
let presentation = AlarmPresentation(
alert: AlarmPresentation.Alert(
title: "Timer Complete",
stopButton: .stopButton,
secondaryButton: .repeatButton,
secondaryButtonBehavior: .countdown
),
countdown: AlarmPresentation.Countdown(
title: "Cooking Timer",
pauseButton: .pauseButton
),
paused: AlarmPresentation.Paused(
title: "Timer Paused",
resumeButton: .resumeButton
)
)结合三种状态实现完整的计时器体验:
swift
let presentation = AlarmPresentation(
alert: AlarmPresentation.Alert(
title: "Timer Complete",
stopButton: .stopButton,
secondaryButton: .repeatButton,
secondaryButtonBehavior: .countdown
),
countdown: AlarmPresentation.Countdown(
title: "Cooking Timer",
pauseButton: .pauseButton
),
paused: AlarmPresentation.Paused(
title: "Timer Paused",
resumeButton: .resumeButton
)
)Part 5: Managing Alarms
第五部分:管理闹钟
Retrieve All Alarms
获取所有闹钟
swift
let alarms = try AlarmManager.shared.alarmsswift
let alarms = try AlarmManager.shared.alarmsPause / Resume
暂停/恢复
swift
try await AlarmManager.shared.pause(id: alarmID)
try await AlarmManager.shared.resume(id: alarmID)swift
try await AlarmManager.shared.pause(id: alarmID)
try await AlarmManager.shared.resume(id: alarmID)Cancel
取消
swift
try await AlarmManager.shared.cancel(id: alarmID)swift
try await AlarmManager.shared.cancel(id: alarmID)Observe Alarm Updates
监听闹钟更新
Use to keep UI in sync. An alarm absent from the emitted array is no longer scheduled.
alarmUpdatesswift
for await alarms in AlarmManager.shared.alarmUpdates {
self.alarms = alarms
}使用保持UI同步。如果某个闹钟不在返回的数组中,则表示该闹钟已不再被调度。
alarmUpdatesswift
for await alarms in AlarmManager.shared.alarmUpdates {
self.alarms = alarms
}Part 6: Live Activity Integration
第六部分:Live Activity集成
AlarmKit alarms appear in the Dynamic Island and Lock Screen through . Add a Widget Extension target and implement the widget using .
ActivityConfigurationAlarmAttributesswift
struct AlarmWidgetView: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: AlarmAttributes<YourMetadata>.self) { context in
// Lock Screen presentation
VStack {
Text(context.attributes.presentation.alert.title)
if context.state.mode == .countdown {
Text(
timerInterval: context.state.countdownEndDate
.timeIntervalSinceNow,
countsDown: true
)
.bold()
}
}
.padding()
} dynamicIsland: { context in
DynamicIsland {
DynamicIslandExpandedRegion(.leading) {
Text(context.attributes.presentation.alert.title)
}
DynamicIslandExpandedRegion(.trailing) {
if context.state.mode == .countdown {
Text(
timerInterval: context.state.countdownEndDate
.timeIntervalSinceNow,
countsDown: true
)
}
}
} compactLeading: {
Image(systemName: "alarm")
} compactTrailing: {
if context.state.mode == .countdown {
Text(
timerInterval: context.state.countdownEndDate
.timeIntervalSinceNow,
countsDown: true
)
}
} minimal: {
Image(systemName: "alarm")
}
}
}
}AlarmKit闹钟通过在Dynamic Island和锁屏界面展示。需添加Widget Extension目标,并使用实现小组件。
ActivityConfigurationAlarmAttributesswift
struct AlarmWidgetView: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: AlarmAttributes<YourMetadata>.self) { context in
// 锁屏界面展示
VStack {
Text(context.attributes.presentation.alert.title)
if context.state.mode == .countdown {
Text(
timerInterval: context.state.countdownEndDate
.timeIntervalSinceNow,
countsDown: true
)
.bold()
}
}
.padding()
} dynamicIsland: { context in
DynamicIsland {
DynamicIslandExpandedRegion(.leading) {
Text(context.attributes.presentation.alert.title)
}
DynamicIslandExpandedRegion(.trailing) {
if context.state.mode == .countdown {
Text(
timerInterval: context.state.countdownEndDate
.timeIntervalSinceNow,
countsDown: true
)
}
}
} compactLeading: {
Image(systemName: "alarm")
} compactTrailing: {
if context.state.mode == .countdown {
Text(
timerInterval: context.state.countdownEndDate
.timeIntervalSinceNow,
countsDown: true
)
}
} minimal: {
Image(systemName: "alarm")
}
}
}
}Part 7: SwiftUI Integration
第七部分:SwiftUI集成
ViewModel Pattern with @Observable
结合@Observable的ViewModel模式
swift
import AlarmKit
@Observable
class AlarmViewModel {
var alarms: [Alarm] = []
private let manager = AlarmManager.shared
func requestAuthorization() {
Task {
_ = try? await manager.requestAuthorization()
}
}
func loadAndObserve() {
Task {
alarms = (try? manager.alarms) ?? []
for await updated in manager.alarmUpdates {
alarms = updated
}
}
}
func addAlarm(hour: Int, minute: Int, weekdays: Set<Locale.Weekday>) {
Task {
let time = Alarm.Schedule.Relative.Time(hour: hour, minute: minute)
let schedule = Alarm.Schedule.relative(.init(
time: time,
repeats: weekdays.isEmpty ? .never : .weekly(Array(weekdays))
))
let alert = AlarmPresentation.Alert(
title: "Alarm",
stopButton: .stopButton,
secondaryButton: .snoozeButton,
secondaryButtonBehavior: .countdown
)
struct EmptyMetadata: AlarmMetadata {}
let config = AlarmManager.AlarmConfiguration(
countdownDuration: Alarm.CountdownDuration(
preAlert: nil, postAlert: 9 * 60
),
schedule: schedule,
attributes: AlarmAttributes(
presentation: AlarmPresentation(alert: alert),
metadata: EmptyMetadata(),
tintColor: .blue
),
sound: .default
)
_ = try? await manager.schedule(id: UUID(), configuration: config)
}
}
func cancel(id: UUID) {
Task { try? await manager.cancel(id: id) }
}
func togglePause(id: UUID, isPaused: Bool) {
Task {
if isPaused {
try? await manager.resume(id: id)
} else {
try? await manager.pause(id: id)
}
}
}
}swift
import AlarmKit
@Observable
class AlarmViewModel {
var alarms: [Alarm] = []
private let manager = AlarmManager.shared
func requestAuthorization() {
Task {
_ = try? await manager.requestAuthorization()
}
}
func loadAndObserve() {
Task {
alarms = (try? manager.alarms) ?? []
for await updated in manager.alarmUpdates {
alarms = updated
}
}
}
func addAlarm(hour: Int, minute: Int, weekdays: Set<Locale.Weekday>) {
Task {
let time = Alarm.Schedule.Relative.Time(hour: hour, minute: minute)
let schedule = Alarm.Schedule.relative(.init(
time: time,
repeats: weekdays.isEmpty ? .never : .weekly(Array(weekdays))
))
let alert = AlarmPresentation.Alert(
title: "Alarm",
stopButton: .stopButton,
secondaryButton: .snoozeButton,
secondaryButtonBehavior: .countdown
)
struct EmptyMetadata: AlarmMetadata {}
let config = AlarmManager.AlarmConfiguration(
countdownDuration: Alarm.CountdownDuration(
preAlert: nil, postAlert: 9 * 60
),
schedule: schedule,
attributes: AlarmAttributes(
presentation: AlarmPresentation(alert: alert),
metadata: EmptyMetadata(),
tintColor: .blue
),
sound: .default
)
_ = try? await manager.schedule(id: UUID(), configuration: config)
}
}
func cancel(id: UUID) {
Task { try? await manager.cancel(id: id) }
}
func togglePause(id: UUID, isPaused: Bool) {
Task {
if isPaused {
try? await manager.resume(id: id)
} else {
try? await manager.pause(id: id)
}
}
}
}Alarm List View
闹钟列表视图
swift
struct AlarmListView: View {
@State private var viewModel = AlarmViewModel()
var body: some View {
NavigationStack {
List(viewModel.alarms, id: \.id) { alarm in
AlarmRow(alarm: alarm, viewModel: viewModel)
}
.navigationTitle("Alarms")
.onAppear {
viewModel.requestAuthorization()
viewModel.loadAndObserve()
}
}
}
}swift
struct AlarmListView: View {
@State private var viewModel = AlarmViewModel()
var body: some View {
NavigationStack {
List(viewModel.alarms, id: \.id) { alarm in
AlarmRow(alarm: alarm, viewModel: viewModel)
}
.navigationTitle("Alarms")
.onAppear {
viewModel.requestAuthorization()
viewModel.loadAndObserve()
}
}
}
}Part 8: Best Practices
第八部分:最佳实践
| Practice | Detail |
|---|---|
| Request authorization early | On first launch or first alarm creation attempt |
| Handle denial gracefully | Guide users to Settings if permission was denied |
| Persist alarm UUIDs | Store IDs to manage alarms across app launches |
| Implement widget extension | Required for countdown/Dynamic Island presentation |
Use | Keep UI in sync; don't poll or cache stale state |
| Test on physical device | Alarm sounds, notifications, and Live Activities require real hardware |
| Respect system limits | There is a system-imposed cap on alarms per app |
Use | Not |
| 实践建议 | 详细说明 |
|---|---|
| 尽早请求授权 | 在首次启动或首次尝试创建闹钟时请求 |
| 优雅处理权限拒绝 | 如果权限被拒绝,引导用户前往设置界面开启 |
| 持久化闹钟UUID | 存储ID以在应用重启后管理闹钟 |
| 实现小组件扩展 | 倒计时/Dynamic Island展示的必要条件 |
使用 | 保持UI同步;不要轮询或缓存过期状态 |
| 在物理设备上测试 | 闹钟声音、通知和Live Activities需要真实硬件支持 |
| 遵守系统限制 | 系统对每个应用可设置的闹钟数量有上限 |
使用 | 正确的属性名称是 |
Resources
参考资源
WWDC: 2025-230
Docs: /alarmkit, /alarmkit/alarmmanager, /alarmkit/alarm, /alarmkit/alarmpresentation, /alarmkit/alarmattributes
Skills: axiom-extensions-widgets-ref, axiom-swiftui-26-ref
WWDC: 2025-230
文档: /alarmkit, /alarmkit/alarmmanager, /alarmkit/alarm, /alarmkit/alarmpresentation, /alarmkit/alarmattributes
技能: axiom-extensions-widgets-ref, axiom-swiftui-26-ref