AlarmKit API in Swift: Native iOS Alarms Without Background Hacks

No imageSilviu V.
5211 Jun, 2025

AlarmKit is Apple’s new native framework that finally lets you create fully customizable alarms and timers right inside your app. ⏰

Available from iOS 26.0+

Whether you're building one time or repeating alarms. Countdown timers. Or even adding snooze support...

AlarmKit handles it all including authorization and UI integration. It offers out of the box scheduling. Pausing. Resuming. And canceling. With support for traditional alarm use cases and widget ready designs.

➡️ Check out the WWDC 25 video walkthrough about this API right here.


First, we need to import the new API to access the most important part: the AlarmManager.

This it’s essentially an object that handles alarm operations like:

  • scheduling
  • snoozing
  • canceling
swift
import AlarmKit

Authorization, or when the user gives consent for the app to schedule alarms, is handled conveniently. You can request it manually, or the system will automatically prompt the user the first time an alarm is created in your app.

Just make sure to add the NSAlarmKitUsageDescription key to your app’s Info.plist file.

Along with a clear and user-friendly description explaining why your app needs access to the AlarmKit API. For example, to schedule personalized wake-up alarms or custom reminders.

Here is also the code snippet that lets you request authorization manually when needed:

swift
do { let state = try await alarmManager.requestAuthorization() // Use state to handle the app flow accordingly } catch { print("Error occurred while requesting authorization: \(error)") return false }

You can also use AlarmManager to check the authorization state. If access is not granted, you can manually request it. Once authorized, you can proceed with scheduling alarms. If access is denied, Apple recommends informing the user within your app that the alarm will NOT be scheduled.

Additionally, you can use this authorization state to adjust your app’s interface or configure different views accordingly.

Secondly, let’s see how to schedule a one-time alarm or a fixed-time alarm. All you need is a specific future date, and then you can schedule it like this:

swift
import AlarmKit func scheduleLunchReminder() { /* ... */ let lunchDateComponents = DateComponents( calendar: .current, year: 2025, month: 6, day: 15, hour: 12, minute: 30) let lunchReminderDate = Calendar.current.date(from: lunchDateComponents)! let scheduleFixed = Alarm.Schedule.fixed(lunchReminderDate) /* ... */ }

But what if you want to schedule an alarm to repeat three times a week at 8 AM? You can easily set that up like this: ✅

swift
import AlarmKit func setupMorningRoutineAlarm() { /* ... */ let morningTime = Alarm.Schedule.Relative.Time(hour: 8, minute: 0) let repeatDays = Alarm.Schedule.Relative.Recurrence.weekly([ .tuesday, .thursday, .saturday ]) let alarmSchedule = Alarm.Schedule.Relative(time: morningTime, repeats: repeatDays) /* ... */ }

Third, we have the appearance of alarms. Whether they show up in the Dynamic Island or as a full-screen alert.

According to the documentation, we can customize a Stop button for the alarm with a text, a foreground color, and an SF Symbol icon. When the alarm appears in the Dynamic Island, only the system image (icon) is shown, not the text.

swift
let stopButton = AlarmButton( text: "Dismiss", textColor: .white, systemImageName: "stop.circle" )

Next, let's create the AlarmPresentation.Alert, which includes a title and also allows us to attach the Stop button we defined earlier.

swift
let alertPresentation = AlarmPresentation.Alert( title: "Food Ready!", stopButton: stopButton )

Then, using AlarmAttributes, essentially a wrapper around the ActivityAttributes introduced in iOS 16, we can pass additional metadata and customize the appearance of the alarm. For example, we can set a tint color to visually differentiate your app's alarm from others.

swift
let attributes = AlarmAttributes<YourMetadata>( presentation: AlarmPresentation( alert: alertPresentation), tintColor: Color.blue )

To tie everything together, we use AlarmConfiguration, where we pass in the attributes along with a countdown duration

swift
let id = UUID() let alarmConfiguration = AlarmConfiguration( countdownDuration: duration, attributes: attributes) try await AlarmManager.shared.schedule(id: id, configuration: alarmConfiguration)

And last but not least, my favorite feature is that AlarmKit lets us run custom code when the user taps an alarm button. To achieve this, we use an AppIntent. You can create one for the stop button or even for a secondary action.

What’s really cool is that even if the app is completely closed, not even running in the background, the alarm can still launch your app when the user taps on it. 🚀

Let’s declare an Open button with custom text and an SF Symbol, just like we did earlier. ✅

swift
let openButton = AlarmButton( text: "Open", textColor: .white, systemImageName: "arrow.right.circle.fill" )

Now let’s add the Open button as a secondaryButton in an AlarmPresentation.Alert. For the secondaryButtonBehavior, we’ll set it to .custom.

swift
let alertPresentation = AlarmPresentation.Alert( title: "Alarm Title!", stopButton: stopButton, secondaryButton: openButton, secondaryButtonBehavior: .custom )

After setting up the attributes, metadata, and other UI details, we create the AlarmConfiguration, where we specify our Launch App intent as the secondaryIntent.

swift
let id = UUID() let secondaryIntent = LaunchAppIntent(alarmID: id.uuidString) let alarmConfiguration = AlarmConfiguration( countdownDuration: duration, attributes: attributes, secondaryIntent: secondaryIntent )

And our LiveActivityIntent:

swift
public struct LaunchAppIntent: LiveActivityIntent { public func perform() async throws -> some IntentResult { .result() } @Parameter(title: "alarmIdentifier") public var alarmIdentifier: String public static var title: LocalizedStringResource = "Launch Application" public static var description = IntentDescription("Launches the demo app") public static var openAppWhenRun = true public init(alarmIdentifier: String) { self.alarmIdentifier = alarmIdentifier } public init() { self.alarmIdentifier = "" } }

✨ As a bonus, let’s explore how to add a sound to your alarm. The sound file should be included in your app’s main bundle or inside the Library Sounds folder within your app’s data container.

swift
let sound = AlertConfiguration.AlertSound.named("Chime") // then just pass the sound to the AlarmConfiguration let alarmConfiguration = AlarmConfiguration( countdownDuration: duration, attributes: attributes, secondaryIntent: secondaryIntent, sound: sound )

All in all, as Apple suggests, AlarmKit is great for countdowns like cooking timers and recurring alerts with schedules such as wake-up alarms. However, they are not a replacement for other important notifications like critical alerts or time-sensitive notifications.

Thanks for stopping by! 🪴