mcpField
W
widgetkit

widgetkit

github.com/ios-agent开发1265 次安装35 周前更新
代码仓库

关于 widgetkit

面向 Apple 平台 WidgetKit 开发的技能,供构建小组件的开发者参考。内容涵盖组件布局、渲染模式、交互、配置及平台限制。

主要功能

  1. 01小组件结构与时间线
  2. 02适配不同组件尺寸
  3. 03渲染模式处理
  4. 04按钮、切换与深层链接
  5. 05配置类型与平台限制

适用场景

  1. 01创建主屏幕或锁屏小组件
  2. 02为不同尺寸设计自适应布局
  3. 03添加小组件交互和应用跳转

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ios-agent/iosagent.dev --skill widgetkit

安装后在 Claude Code 中输入/widgetkit确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
design-guidelines.md
dimensions.md
interactivity.md
live-activities.md
platforms.md
timelines.md

详细介绍

WidgetKit 开发技能

使用 WidgetKit 在 Apple 平台上构建一目了然、及时更新的体验。

快速开始

创建 Widget 扩展
  1. 文件 → 新建 → 目标 → Widget 扩展
  2. 对于静态 Widget,取消选择“Include Live Activity”和“Include Configuration App Intent”
  3. 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 类型与尺寸

类型平台使用场景
systemSmalliOS、iPadOS、macOS、visionOS单个轻点目标,一目了然的信息
systemMediumiOS、iPadOS、macOS、visionOS多个数据点、交互元素
systemLargeiOS、iPadOS、macOS、visionOS丰富内容、多种交互
systemExtraLargeiPadOS、macOS、visionOS仪表板式布局
accessoryCirculariOS 锁定屏幕、watchOS精简信息、仪表样式
accessoryRectangulariOS 锁定屏幕、watchOS2-3 行文本
accessoryInlineiOS 锁定屏幕、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