axiom-alarmkit-ref について
AlarmKitを使うiOSアプリ開発者向けのSwiftリファレンススキルです。権限、アラームやタイマーの設定、画面表示、Live Activity連携を解説します。
主な機能
- 01AlarmKit APIコンポーネントの解説
- 02権限要求と状態の監視
- 03単発・繰り返しアラーム
- 04カウントダウン、一時停止、再開、スヌーズ
- 05アラーム表示とLive Activityの指針
活用シーン
- 01iOSアプリへの時刻指定アラームの実装
- 02一時停止・再開できるタイマーの追加
- 03ロック画面とDynamic Islandのアラーム画面構築
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ charleswiltgen/ axiom --skill axiom-alarmkit-refインストール後、Claude Code で/axiom-alarmkit-refを入力して読み込まれたか確認します。
詳細
AlarmKit リファレンス
アラームやカウントダウンタイマーをスケジュールし、システムレベルのアラート、Dynamic Island との連携、集中モード/消音モードの解除を実現する Apple のフレームワーク、AlarmKit の完全な API リファレンスです。
概要
AlarmKit を使うと、標準の「時計」アプリと同様に動作するアラームやタイマーをアプリで作成できます。おやすみモードを解除し、Dynamic Island に表示され、ロック画面にも表示されます。このフレームワークでは、AlarmManager を中心とする少数の型を通じて、スケジュール設定、スヌーズ、一時停止/再開、UI の表示を処理します。
システム要件
- iOS 26 以降(AlarmKit は iOS 26 で導入されました)
- Live Activity / Dynamic Island での表示には Widget Extension が必要です
- アラーム音と通知のテストには 実機を推奨します
パート 1:主要コンポーネント
AlarmManager
すべてのアラーム操作を行うためのシングルトンのエントリーポイントです。
import AlarmKit
let manager = AlarmManager.shared
スケジュール設定、キャンセル、監視はすべて、この共有インスタンスを介して行います。
Alarm
一度だけ、または繰り返しのスケジュールでアラートを鳴らすアラームを記述します。
struct Alarm {
var id: UUID
var schedule: Schedule?
var countdownDuration: CountdownDuration?
var state: AlarmState
}
AlarmPresentation
アラート中、カウントダウン中、一時停止中の 3 つの状態におけるアラーム UI のコンテンツです。
struct AlarmPresentation {
var alert: Alert // Required: shown when alarm fires
var countdown: Countdown? // Optional: shown during countdown
var paused: Paused? // Optional: shown when paused
}
AlarmAttributes
プレゼンテーションとアプリ固有のメタデータ、ティントカラーを組み合わせる汎用コンテナーです。Live Activity ウィジェットの設定に使います。
struct AlarmAttributes<Metadata: AlarmMetadata> {
var presentation: AlarmPresentation
var metadata: Metadata
var tintColor: Color
}
AlarmMetadata
アラームに付加するアプリ固有のデータ用プロトコルです。最小限の用途では空の構造体に適合させ、より豊かな UI にはプロパティを追加します。
struct RecipeMetadata: AlarmMetadata {
let recipeName: String
let cookingStep: String
}
パート 2:許可
アラームをスケジュールする前に、アプリで許可をリクエストする必要があります。Info.plist に NSAlarmKitUsageDescription を追加してください。
許可のリクエスト
func requestAlarmAuthorization() async -> Bool {
do {
let state = try await AlarmManager.shared.requestAuthorization()
return state == .authorized
} catch {
print("Authorization error: \(error)")
return false
}
}
現在の状態の確認
現在の値を読み取るには、authorizationStatus ではなく authorizationState を使います。
let state = await AlarmManager.shared.authorizationState
// .authorized | .denied | .notDetermined
許可の変更の監視
for await authState in AlarmManager.shared.authorizationUpdates {
switch authState {
case .authorized: enableAlarmUI()
case .denied: showPermissionPrompt()
case .notDetermined: break
@unknown default: break
}
}
パート 3:アラームのスケジュール設定
各アラームには UUID、AlarmManager.AlarmConfiguration、および schedule(id:configuration:) の呼び出しが必要です。
一度限りのアラーム
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)
繰り返しアラーム
特定の曜日を指定するには .weekly(Array(weekdays)) を使います。
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])
))
カウントダウンタイマー
schedule: nil を設定し、preAlert 間隔を指定して countdownDuration を渡します。
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
)
タイマーは一時停止/再開に対応しています。また、AlarmPresentation.countdown を指定すると、カウントダウン中のプレゼンテーションが表示されます。
スヌーズの設定
スヌーズでは、CountdownDuration.postAlert と .snoozeButton のセカンダリアクションを組み合わせます。
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
)
パート 4:アラーム UI のカスタマイズ
アラートのプレゼンテーション
アラームが鳴ると、アラート状態が表示されます。停止ボタンは必須で、セカンダリボタンは任意です。
// 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
)
カウントダウンのプレゼンテーション
タイマーのカウントダウン中に表示されます。countdownDuration.preAlert が設定されたアラームにのみ関係します。
let countdown = AlarmPresentation.Countdown(
title: "Timer Running",
pauseButton: .pauseButton
)
一時停止中のプレゼンテーション
カウントダウンタイマーが一時停止されているときに表示されます。
let paused = AlarmPresentation.Paused(
title: "Timer Paused",
resumeButton: .resumeButton
)
3 つの状態すべてを含むプレゼンテーション
3 つすべてを組み合わせて、タイマーの機能を完全に実現します。
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
)
)
パート 5:アラームの管理
すべてのアラームを取得
let alarms = try AlarmManager.shared.alarms
一時停止/再開
try await AlarmManager.shared.pause(id: alarmID)
try await AlarmManager.shared.resume(id: alarmID)
キャンセル
try await AlarmManager.shared.cancel(id: alarmID)
アラームの更新を監視
alarmUpdates を使って UI を最新の状態に保ちます。通知された配列に含まれないアラームは、スケジュールされていません。
for await alarms in AlarmManager.shared.alarmUpdates {
self.alarms = alarms
}
パート 6:Live Activity との連携
AlarmKit のアラームは、ActivityConfiguration を通じて Dynamic Island とロック画面に表示されます。Widget Extension ターゲットを追加し、AlarmAttributes を使ってウィジェットを実装してください。
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")
}
}
}
}
パート 7:SwiftUI との連携
@Observable を使った ViewModel パターン
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)
}
}
}
}
アラーム一覧ビュー
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()
}
}
}
}
パート 8:ベストプラクティス
| 実践項目 | 詳細 |
|---|---|
| 早めに認証をリクエストする | 初回起動時、または初めてアラームを作成しようとするとき |
| 拒否された場合も適切に対処する | 権限が拒否された場合は、ユーザーに「設定」への移動を案内します |
| アラームの UUID を保持する | アプリの起動をまたいでアラームを管理できるよう、ID を保存します |
| ウィジェット拡張機能を実装する | カウントダウン/Dynamic Island に表示するために必要です |
alarmUpdates を使用する | UI を同期した状態に保ちます。ポーリングしたり、古い状態をキャッシュしたりしないでください |
| 実機でテストする | アラーム音、通知、ライブアクティビティには実機が必要です |
| システムの制限を守る | アプリごとに、システムによるアラーム数の上限があります |
authorizationState を使用する | authorizationStatus ではありません。正しいプロパティ名は authorizationState です |
リソース
WWDC:2025-230
ドキュメント:/alarmkit、/alarmkit/alarmmanager、/alarmkit/alarm、/alarmkit/alarmpresentation、/alarmkit/alarmattributes
スキル:axiom-extensions-widgets-ref、axiom-swiftui-26-ref