mcpField
A
axiom-alarmkit-ref

axiom-alarmkit-ref

github.com/charleswiltgen開発1.2k88 回インストール今日更新
リポジトリ

axiom-alarmkit-ref について

AlarmKitを使うiOSアプリ開発者向けのSwiftリファレンススキルです。権限、アラームやタイマーの設定、画面表示、Live Activity連携を解説します。

主な機能

  1. 01AlarmKit APIコンポーネントの解説
  2. 02権限要求と状態の監視
  3. 03単発・繰り返しアラーム
  4. 04カウントダウン、一時停止、再開、スヌーズ
  5. 05アラーム表示とLive Activityの指針

活用シーン

  1. 01iOSアプリへの時刻指定アラームの実装
  2. 02一時停止・再開できるタイマーの追加
  3. 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

コメント