关于 widgetkit
面向 Apple 平台 WidgetKit 开发的技能,供构建小组件的开发者参考。内容涵盖组件布局、渲染模式、交互、配置及平台限制。
主要功能
- 01小组件结构与时间线
- 02适配不同组件尺寸
- 03渲染模式处理
- 04按钮、切换与深层链接
- 05配置类型与平台限制
适用场景
- 01创建主屏幕或锁屏小组件
- 02为不同尺寸设计自适应布局
- 03添加小组件交互和应用跳转
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ ios-agent/ iosagent.dev --skill widgetkit安装后在 Claude Code 中输入/widgetkit确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/design-guidelines.mddimensions.mdinteractivity.mdlive-activities.mdplatforms.mdtimelines.md详细介绍
WidgetKit 开发技能
使用 WidgetKit 在 Apple 平台上构建一目了然、及时更新的体验。
快速开始
创建 Widget 扩展
- 文件 → 新建 → 目标 → Widget 扩展
- 对于静态 Widget,取消选择“Include Live Activity”和“Include Configuration App Intent”
- Widget 需要:
Widget协议、TimelineProvider和 SwiftUI 视图
最小 Widget 结构
@main
struct MyWidget: Widget {
var body: some WidgetConfiguration {
StaticConfiguration(
kind: "com.app.mywidget",
provider: Provider()
) { entry in
MyWidgetView(entry: entry)
}
.configurationDisplayName("My Widget")
.description("Shows key information")
.supportedFamilies([.systemSmall, .systemMedium])
}
}
struct Provider: TimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: .now)
}
func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> Void) {
completion(SimpleEntry(date: .now))
}
func getTimeline(in context: Context, completion: @escaping (Timeline<SimpleEntry>) -> Void) {
let entry = SimpleEntry(date: .now)
let nextUpdate = Calendar.current.date(byAdding: .minute, value: 15, to: .now)!
completion(Timeline(entries: [entry], policy: .after(nextUpdate)))
}
}
struct SimpleEntry: TimelineEntry {
let date: Date
}
Widget 类型与尺寸
| 类型 | 平台 | 使用场景 |
|---|---|---|
systemSmall | iOS、iPadOS、macOS、visionOS | 单个轻点目标,一目了然的信息 |
systemMedium | iOS、iPadOS、macOS、visionOS | 多个数据点、交互元素 |
systemLarge | iOS、iPadOS、macOS、visionOS | 丰富内容、多种交互 |
systemExtraLarge | iPadOS、macOS、visionOS | 仪表板式布局 |
accessoryCircular | iOS 锁定屏幕、watchOS | 精简信息、仪表样式 |
accessoryRectangular | iOS 锁定屏幕、watchOS | 2-3 行文本 |
accessoryInline | iOS 锁定屏幕、watchOS | 单行文本 + 可选图像 |
accessoryCorner | 仅 watchOS | 转角复杂功能 |
适配 Widget 类型
struct MyWidgetView: View {
@Environment(\.widgetFamily) var family
var body: some View {
switch family {
case .systemSmall: CompactView()
case .systemMedium: MediumView()
case .systemLarge: DetailedView()
case .accessoryCircular: GaugeView()
case .accessoryRectangular: RectangularView()
default: CompactView()
}
}
}
渲染模式
Widget 会根据使用情境以不同方式渲染:
| 模式 | 使用场景 | 行为 |
|---|---|---|
fullColor | 主屏幕(iOS 17-)、macOS 桌面 | 保留完整色彩 |
accented | 主屏幕着色/透明效果、visionOS、watchOS | 分为强调色组和主色组 |
vibrant | 锁定屏幕、待机 | 去饱和、模糊效果 |
@Environment(\.widgetRenderingMode) var renderingMode
var body: some View {
switch renderingMode {
case .fullColor: FullColorView()
case .accented: AccentedView()
case .vibrant: VibrantView()
@unknown default: FullColorView()
}
}
交互
按钮与开关(iOS 17+)
Button(intent: RefreshIntent()) {
Label("Refresh", systemImage: "arrow.clockwise")
}
Toggle(isOn: $isEnabled, intent: ToggleIntent()) {
Text("Enable")
}
深度链接
MyWidgetView()
.widgetURL(URL(string: "myapp://detail/123")!)
// Or for multiple links in larger widgets:
Link(destination: URL(string: "myapp://item/1")!) {
ItemView()
}
配置类型
| 类型 | 使用场景 |
|---|---|
StaticConfiguration | 无需用户配置 |
AppIntentConfiguration | 用户可配置(iOS 17+) |
ActivityConfiguration | 实时活动 |
参考文档
- 时间线与更新:时间线提供程序、重新加载策略、推送更新
- 交互:按钮、开关、App Intents、深度链接
- 实时活动:ActivityKit、灵动岛、锁定屏幕
- 设计指南:HIG 最佳实践、布局、排版
- 平台差异:iOS、watchOS、macOS、visionOS 的差异
- 尺寸:各设备上所有 Widget 类型的精确尺寸
主要限制
- 不支持实时更新:使用时间线;系统会批量处理更新
- 预算有限:根据使用情况,每天约可刷新 40-70 次
- 不支持连续动画:仅支持最长 2 秒的过渡动画
- 仅限 SwiftUI:不支持 UIKit 视图
- 无状态:渲染之间不会保留状态
- 视图中不能访问网络:只能在时间线提供程序中获取数据
常见模式
与主应用共享数据
// Use App Groups
let sharedDefaults = UserDefaults(suiteName: "group.com.app.shared")
// Or shared container
let containerURL = FileManager.default.containerURL(
forSecurityApplicationGroupIdentifier: "group.com.app.shared"
)
强制刷新 Widget
import WidgetKit
WidgetCenter.shared.reloadTimelines(ofKind: "com.app.mywidget")
WidgetCenter.shared.reloadAllTimelines()
敏感内容占位符
.privacySensitive() // Redacts when device locked
评论
支持 Markdown