alarm
系统闹钟调度(AlarmKit,iOS 18+)。
系统闹钟调度(AlarmKit):创建、列出和取消闹钟。
边界:需要 iOS 26+ 且设备支持 AlarmKit;先用is_available()判断。与 notification 本地通知不同——闹钟走系统闹钟体验。调度放在用户操作回调里,不要在body()中调用。
#模块概览
| 项 | 说明 |
|---|---|
| 导入 | import alarm |
| 适合做什么 | 起床提醒、定时闹钟、重复闹钟 |
| 调用时机 | schedule() / cancel() 放在按钮回调 |
| 推荐顺序 | is_available() → request_authorization() → schedule() → list_alarms() |
| 标识符 | schedule() 返回 alarm_id,用于 cancel() |
#快速开始
下面脚本检查可用性、申请权限、创建并列出闹钟:
已复制
import alarm
if not alarm.is_available():
print("当前系统不支持 AlarmKit(需 iOS 26+)")
else:
try:
if alarm.request_authorization():
alarm_id = alarm.schedule("起床", 7, 30, repeats=True)
print("已创建:", alarm_id)
print(alarm.list_alarms())
alarm.cancel(alarm_id)
else:
print("未获得闹钟权限")
except alarm.AlarmError as exc:
print("闹钟操作失败:", exc, f"code={exc.code}")
#AppUI 示例
授权和调度放在按钮回调;列表展示当前闹钟。
已复制
import appui
import alarm
state = appui.State(
available=alarm.is_available(),
auth="未查询",
alarms=[],
status="点击按钮管理闹钟",
)
def refresh_list():
try:
state.alarms = alarm.list_alarms() or []
except alarm.AlarmError as exc:
state.status = f"读取失败: {exc}"
def request_access():
if not state.available:
state.status = "当前系统不支持 AlarmKit"
return
try:
ok = alarm.request_authorization()
state.auth = "已授权" if ok else "未授权"
state.status = state.auth
if ok:
refresh_list()
except alarm.AlarmError as exc:
state.status = f"授权失败: {exc}"
def add_demo_alarm():
if not state.available:
state.status = "系统不支持"
return
try:
if not alarm.request_authorization():
state.status = "请先授权"
return
alarm.schedule("演示闹钟", 8, 0, repeats=False)
refresh_list()
state.status = "已添加 08:00 闹钟"
except alarm.AlarmError as exc:
state.status = f"创建失败: {exc}"
def cancel_first():
if not state.alarms:
state.status = "没有可取消的闹钟"
return
try:
alarm_id = state.alarms[0].get("alarm_id")
if alarm_id:
alarm.cancel(alarm_id)
refresh_list()
state.status = f"已取消 {alarm_id[:8]}…"
except alarm.AlarmError as exc:
state.status = f"取消失败: {exc}"
def body():
rows = []
for item in state.alarms:
title = item.get("title", "闹钟")
hour = item.get("hour", 0)
minute = item.get("minute", 0)
repeats = "每天" if item.get("repeats") else "一次"
rows.append(
appui.LabeledContent(
title,
value=f"{hour:02d}:{minute:02d} · {repeats}",
)
)
return appui.NavigationStack(
appui.Form([
appui.Section("环境", [
appui.LabeledContent(
"AlarmKit",
value="可用" if state.available else "不可用(需 iOS 26+)",
),
appui.LabeledContent("授权", value=state.auth),
]),
appui.Section("闹钟列表", rows or [
appui.ContentUnavailableView(
"暂无闹钟",
system_image="alarm",
description="点击下方按钮添加",
)
]),
appui.Section("操作", [
appui.Button("申请权限", action=request_access),
appui.Button("添加 08:00 闹钟", action=add_demo_alarm)
.button_style("bordered_prominent"),
appui.Button("取消第一个", action=cancel_first, role="destructive"),
appui.Text(state.status).foreground_color("secondaryLabel"),
], footer="真机 + iOS 26+ 测试;与本地通知是不同能力。"),
]).navigation_title("闹钟")
)
appui.run(body, state=state)
#API 参考
#速查
| API | 作用 |
|---|---|
is_available() | 是否支持 AlarmKit |
request_authorization() | 申请闹钟权限 → bool |
schedule(title, hour, minute, repeats) | 创建闹钟 → alarm_id |
cancel(alarm_id) | 取消指定闹钟 |
list_alarms() | 已调度闹钟列表 |
AlarmError | 操作失败时抛出 |
#可用性与授权
已复制
import alarm
if alarm.is_available():
ok = alarm.request_authorization()
is_available() 在低于 iOS 26 或 Bridge 不可用时返回 False。
#调度
schedule(title, hour, minute, repeats=False)
已复制
alarm_id = alarm.schedule("会议提醒", 9, 15)
alarm_id = alarm.schedule("每日起床", 7, 0, repeats=True)
| 参数 | 说明 |
|---|---|
title | 闹钟标题 |
hour | 0–23 |
minute | 0–59 |
repeats | 是否每天重复 |
返回字符串 alarm_id,传给 cancel() 使用。
list_alarms() — 返回 [{alarm_id, title, hour, minute, repeats, state}, ...]。
cancel(alarm_id) — 取消并移除记录。
#异常
code | 含义 |
|---|---|
unavailable | 系统版本不支持 AlarmKit |
invalid_input | 参数缺失(如没有 title) |
timeout | 异步授权超时 |
#常见错误
| 错误写法 | 后果 | 修正 |
|---|---|---|
不检查 is_available() | 低版本直接崩溃 | 先判断再调度 |
| 当成 notification 用 | API 与体验不同 | 按闹钟场景选模块 |
在 body() 里 schedule() | 刷新时重复创建 | 放进按钮回调 |
丢失 alarm_id | 无法取消 | 保存 schedule() 返回值 |
#相关文档
| 文档 | 用途 |
|---|---|
| notification | 本地通知与角标 |
| permission | 其他权限查询 |
| 原生能力入口 | MiniApp 场景配方 |
#预期效果
运行示例后,界面应出现文档描述的目标结果;若与预期不符,先看「失败路径」并按返回值或日志排查。