AlarmKit in iOS 26: Schedule Native Alarms and Countdown Timers in SwiftUI
Use AlarmKit in iOS 26 to schedule native alarms and countdown timers that override Focus and Silent mode. Full SwiftUI setup with entitlement, authorization, and Live Activity widget code.
AlarmKit is the iOS 26 framework that finally lets third-party apps schedule real alarms and countdown timers that override Focus, Silent mode, and even Do Not Disturb. Local notifications were never allowed to do that. Apple introduced it at WWDC25 alongside iOS 26, and it's the first sanctioned replacement for the background-audio hacks productivity, fitness, and cooking apps have leaned on for a decade. This guide walks through the full setup (entitlement, Info.plist key, authorization, scheduling, the required Live Activity extension) with minimal, complete code you can paste into a fresh Xcode 26 project.
AlarmKit requires iOS 26 or iPadOS 26, the NSAlarmKitUsageDescription Info.plist key, and the AlarmKit entitlement granted through the Apple Developer portal.
AlarmManager.shared handles authorization, scheduling, pausing, resuming, and cancellation. You observe state changes through the alarmUpdates async sequence.
Every scheduled alarm spawns a system-managed Live Activity, so a Widget Extension declaring an ActivityConfiguration over AlarmAttributes is mandatory for countdown alarms.
AlarmKit supports three scheduling shapes: fixed-date, weekly recurrence, and pure countdown, all configured through AlarmConfiguration.
Unlike UserNotifications, AlarmKit alarms break through Focus and Silent mode by design. That's why the entitlement requires Apple review.
In Xcode 26 projects with default MainActor isolation, custom AlarmMetadata types must be marked nonisolated to satisfy the protocol.
What is AlarmKit and what problem does it solve?
AlarmKit is Apple's framework for scheduling system-level alarms and countdown timers from third-party iOS and iPadOS apps. Before iOS 26, the only sanctioned way to wake a user at a specific time was a UNCalendarNotificationTrigger, and notifications respect Focus, Silent, and Do Not Disturb. That meant a meditation app couldn't reliably end a session, a cooking app couldn't guarantee the oven timer rang, and a sleep app had to keep audio looping in the background to imitate an alarm. The AppStore review team was not amused by any of it.
So, AlarmKit replaces those workarounds with a sanctioned API. When you schedule an alarm, the system takes ownership: it shows a Live Activity on the Lock Screen and Dynamic Island, plays the alert sound on a privileged audio session, and ignores Focus modes the same way the built-in Clock app does. The user can stop, snooze, or pause the alarm from system surfaces, so you don't have to build the alerting UI yourself. The trade-off is that Apple gates access behind an entitlement and a privacy prompt, because an app that can pierce Focus is also one that can be abused.
The framework lives in the AlarmKit module and exposes a small surface area: one shared AlarmManager, a few configuration value types, an AlarmAttributes generic for your custom metadata, and an async sequence of state updates. If you've worked with Live Activities and the Dynamic Island you'll feel at home immediately. AlarmKit is built on top of ActivityKit, and an AlarmKit alarm is, internally, a Live Activity with a system-templated UI you don't have to draw. Apple's AlarmKit reference is still light on prose, so most of what's below comes from poking at the API directly.
AlarmKit vs UserNotifications: which one should you use?
Short answer: use AlarmKit only when the user's schedule depends on the alert firing (wake-up alarms, cooking timers, interval-training rounds, medication doses). Use UserNotifications for anything passive (news pings, social activity, marketing nudges). AlarmKit is more powerful and more invasive, and Apple expects you to treat it accordingly during App Review.
Capability
AlarmKit
UserNotifications
Overrides Focus & Silent mode
Yes (by design)
No (Critical Alerts only)
Lock Screen & Dynamic Island UI
System-templated Live Activity
Banner only
Entitlement required
Yes, reviewed by Apple
No (Critical Alerts entitlement only)
Snooze / pause / resume APIs
First-class (pause, resume, countdown)
Schedule a new notification
Native countdown timer support
Yes
No
Reaches Apple Watch Smart Stack
Yes, automatically
Mirrored notification only
Minimum OS
iOS 26 / iPadOS 26
iOS 10+
The two APIs aren't mutually exclusive. A reminder app can use AlarmKit for "take your medication now" alerts and UNTimeIntervalNotificationTrigger for the "you've missed three doses this week" weekly digest. Pick per intent, not per app.
Project setup: entitlement, Info.plist, and capability
Three pieces have to be in place before AlarmManager will return anything but an authorization error. Skipping any of them produces silent failures that are painful to debug, because the framework throws a generic AlarmManager.AuthorizationError.notAuthorized whether the problem is the entitlement, the plist key, or a denied prompt.
Add the Info.plist key
<key>NSAlarmKitUsageDescription</key>
<string>Used to alert you when your focus session ends, even if your iPhone is on silent.</string>
Keep the string concrete. "Used for alarms" is a rejection waiting to happen; tell the user when and why the alarm will fire.
Add the capability in Xcode
In the target's Signing & Capabilities tab, add AlarmKit. Xcode 26 will refuse to add the capability if the App ID on Apple Developer doesn't yet carry the entitlement; once Apple approves your request, regenerate the provisioning profile and the toggle becomes available.
How do you request AlarmKit authorization?
Authorization is a single async call on the shared manager. You can let scheduling trigger the prompt implicitly, but I prefer an explicit gate so I can show a contextual pre-prompt that explains the trade-off before iOS shows the system alert. Pre-prompts dramatically improve grant rates on any permission iOS users have learned to be suspicious of (and AlarmKit is definitely one of them).
import AlarmKit
@MainActor
final class AlarmAuthorization {
static let shared = AlarmAuthorization()
private let manager = AlarmManager.shared
func ensureAuthorized() async throws {
switch manager.authorizationState {
case .authorized:
return
case .denied:
throw AlarmAuthorization.Error.denied
case .notDetermined:
let state = try await manager.requestAuthorization()
guard state == .authorized else {
throw AlarmAuthorization.Error.denied
}
@unknown default:
throw AlarmAuthorization.Error.unknown
}
}
enum Error: Swift.Error { case denied, unknown }
}
The @unknown default case isn't paranoia. Apple has historically added authorization states between iOS releases (think provisional for notifications), and the compiler will warn you the day they do it again.
Schedule a countdown timer with AlarmKit
A countdown alarm is the simplest shape. You hand the manager an AlarmConfiguration with a countdownDuration, an attributes bundle describing how the system Live Activity should look, and a unique UUID. Everything else is optional.
A few things are easy to miss the first time. The stopButton is required on the alert presentation, but the pauseButton on the countdown is optional. Omit it if your domain doesn't support pausing (an oven timer doesn't). preAlert is the duration counting down to the alert; postAlert is an optional additional interval that keeps the alarm in a "post" state after firing, which is useful for "cooling down" UI where the alarm has rung but the user hasn't acknowledged it yet.
Schedule fixed and recurring alarms
For wake-up alarms you want a fixed date, optionally with weekly recurrence. AlarmKit models this with Alarm.Schedule, which has two cases: .fixed(Date) and .relative(Alarm.Schedule.Relative). The relative form carries an hour/minute plus an optional recurrence rule.
The secondaryButtonBehavior: .countdown is what makes snooze work. Tapping snooze transitions the alarm into a countdown state for the duration you specify in the postAlert of a countdown configuration, or a default 9-minute Apple snooze if you don't. secondaryIntent takes an App Intent if you want the secondary button to launch into your app and run custom logic instead.
Build the required Live Activity widget extension
This is the step every first-timer skips and then spends an afternoon debugging. I hit this exact bug shipping a Pomodoro side-project last month: alarm scheduled fine, no error in the console, and absolutely nothing happened when the timer hit zero. Countdown alarms require a Widget Extension that declares an ActivityConfiguration over your AlarmAttributes. Without it, the system dismisses the alarm silently within seconds of scheduling. No error, no log.
In Xcode 26, add a new Widget Extension target, then replace the generated widget bundle with the bare minimum:
The context.state.mode tells you whether the alarm is counting down, paused, alerting, or post-alert. Switch on it to show different UI for each phase. The widget extension shares the same module as your FocusTimerMetadata type only if you mark the type's file membership for both targets. Don't forget that checkbox in the file inspector or you'll get a confusing "cannot find type in scope" build error in the widget target.
Observe and manage alarm state with alarmUpdates
The manager exposes an AsyncSequence that emits the full list of currently-known alarms whenever any of them changes. Bind it to an @Observable store and SwiftUI will redraw automatically, much like the pattern in the @Observable macro guide.
pause, resume, cancel, and stop round out the lifecycle. stop ends an alarm that's currently alerting; cancel removes one that hasn't fired yet. The system retains the UUID across launches, so persist any IDs you care about (Keychain or a small SwiftData table works fine) so a user can manage their alarms even after force-quitting your app.
Common AlarmKit pitfalls and how to avoid them
A handful of issues account for nearly every "why won't my alarm ring" thread on the Apple Developer Forums AlarmKit tag. None of them are documented prominently, so consider this the dog-eared page of the manual.
MainActor isolation breaks the AlarmMetadata conformance
Projects created with Xcode 26 default to actor-isolated types, but AlarmMetadata requires Sendable with no isolation. Mark your metadata type explicitly:
nonisolated struct FocusTimerMetadata: AlarmMetadata { let sessionName: String }
Without nonisolated, you'll see a compile error that points at the protocol conformance and not at the isolation, which is doubly confusing. (The same gotcha exists with ActivityKit attributes; see also the notes in our Swift 6.2 approachable concurrency guide on opting out of default isolation.)
If you schedule a countdown alarm but never registered a matching ActivityConfiguration, the alarm disappears within a few seconds. Always add the widget target first, and only then start scheduling.
The entitlement does not work on the Simulator without a profile
The iOS Simulator honors the entitlement, but you still need a provisioning profile that carries it. Sign your debug build with the same profile you use for TestFlight, or you'll get authorizationError.missingEntitlement the first time you call schedule.
There's an undocumented per-app cap on scheduled alarms
In iOS 26.0 the cap appears to be 64 active alarms per app. Exceeding it throws AlarmManager.SchedulingError.limitReached. Treat alarms as a scarce resource: prefer one recurring alarm with a weekly recurrence rule over seven daily fixed alarms, and cancel completed alarms eagerly inside your alarmUpdates observer.
Frequently Asked Questions
Does AlarmKit work on iOS 18 or earlier?
No. AlarmKit is iOS 26 and iPadOS 26 only. There's no shim or backport because the framework depends on system audio routing changes introduced in the iOS 26 kernel. Apps that need to support older OS versions should fall back to UserNotifications on iOS 18 and below, gated by an #available(iOS 26.0, *) check.
Do AlarmKit alarms override Focus and Silent mode?
Yes, by design. AlarmKit alarms route through the same privileged audio path as the built-in Clock app, so they break through Silent, Do Not Disturb, and Focus filters. This is also why Apple requires an entitlement and a granted privacy prompt before scheduling will succeed.
How do I get the AlarmKit entitlement approved?
Submit a request through Apple's AlarmKit entitlement form describing your use case. Apple looks for a clear, time-sensitive reason an alarm is appropriate (wake-ups, cooking, workouts, medication) rather than generic reminders. Expect a few business days for review and have screenshots of your alarm UX ready to attach.
Can I schedule an AlarmKit alarm from a Live Activity or widget?
Not directly. Widgets and Live Activities run in extension processes that don't carry the AlarmKit entitlement context. You can, however, declare an AppIntent that schedules the alarm and invoke that intent from a widget button. iOS will route the intent into your main app target where AlarmKit is available.
What's the difference between AlarmKit and Critical Alerts in UserNotifications?
Both override Silent and Do Not Disturb, but Critical Alerts are a single banner-style notification gated by a separate entitlement intended for health and safety scenarios. AlarmKit is the full alarm lifecycle (pause, resume, snooze, countdown, Live Activity) and is the right choice when the user is actively scheduling the alert themselves.
How to use SwiftUI PhotosPicker in iOS 26 for multi-select, video filtering, and file-based loading. Covers race conditions, iCloud progress, and VoiceOver.
Swift RegexBuilder gives you type-safe regular expressions with named captures, inline transforms, and Unicode-correct matching by default. Learn the DSL, compare it to NSRegularExpression, and avoid production traps.
Build SwiftUI Metal shaders in iOS 26 with colorEffect, distortionEffect, and layerEffect. Includes MSL setup, TimelineView animation, and GPU cost tips with working code.