跳到主要内容
知仓学习社ZHICANG

widget-generator

Generate WidgetKit widgets for iOS/macOS home screen and lock screen with timeline providers, interactive elements, and App Intent configuration. Us…

不碰外部(只输出文字)无严重或高危命中rshankras/claude-code-apple-skills

它会碰到什么

扫了多少2 个文本文件,47 KB
它会碰到什么不碰外部(只输出文字)
命中总数0 处
命中统计严重 0 · 高 0 · 中 0 · 低 0

这一栏是扫描器报的事实,不是结论。命中多不等于有毒(安全工具、规则库、示例脚本本来就会包含危险写法),命中少也不等于干净。它和你手上的凭据、文件、网络有什么关系,需要你自己看。

技能内容

Widget Generator

Generate a complete WidgetKit widget implementation with timeline providers, size-specific views, lock screen accessory widgets, interactive elements (iOS 17+), and App Intent configuration.

When This Skill Activates

Use this skill when the user:

  • Asks to "add widgets" or "add a widget" to their app
  • Mentions "WidgetKit" or "home screen widgets"
  • Wants "lock screen widgets" or "accessory widgets"
  • Asks about "widget timelines" or "timeline providers"
  • Wants "interactive widgets" with buttons or toggles
  • Mentions "widget configuration" or "configurable widgets"
  • Asks about "App Intent widgets" or "AppIntentConfiguration"
  • Wants to show data on the home screen or lock screen

Pre-Generation Checks

1. Project Context Detection

  • [ ] Check for existing widget extension target
  • [ ] Check for an existing WidgetBundle
  • [ ] Verify deployment target (iOS 17+ recommended for interactive widgets)
  • [ ] Identify source file locations and project structure

2. Conflict Detection

Search for existing widget code:

Glob: **/*Widget*.swift, **/*TimelineProvider*.swift
Grep: "WidgetKit" or "TimelineProvider" or "WidgetBundle" or "WidgetConfiguration"

If an existing widget extension is found:

  • Ask if the new widget should be added to the existing widget extension
  • Check for an existing WidgetBundle to extend

If a WidgetBundle already exists:

  • Add the new widget to the existing bundle instead of creating a new one
  • Do NOT create a second @main entry point

If widget code with the same name exists:

  • Ask user whether to replace or rename

3. Required Capabilities

Widgets require:

  • A widget extension target (File > New > Target > Widget Extension)
  • App Groups capability if sharing data between the main app and widget
  • iOS 14+ for basic widgets, iOS 16+ for lock screen, iOS 17+ for interactive widgets

Configuration Questions

Ask user via AskUserQuestion:

  1. What is this widget for? (freeform)
  • Examples: weather forecast, task list, fitness stats, quick actions, countdown timer
  • This determines the data model and timeline update strategy
  1. Which widget sizes should be supported?
  • Home screen: systemSmall, systemMedium, systemLarge, systemExtraLarge (iPad only)
  • Lock screen: accessoryCircular, accessoryRectangular, accessoryInline
  • All home screen sizes
  • All home screen + lock screen sizes (recommended)
  1. What type of widget?
  • Static (StaticConfiguration) -- content updated on a schedule, no user configuration
  • Configurable (AppIntentConfiguration, iOS 17+) -- user can choose what the widget displays via long-press edit
  • Interactive (AppIntentConfiguration + Button/Toggle, iOS 17+) -- user can tap buttons or toggles directly on the widget
  1. What is the data source?
  • Local data (UserDefaults, SwiftData, Core Data)
  • Shared data via App Groups (main app writes, widget reads)
  • Network API (fetched during timeline refresh)
  • Combination of local and network
  1. How often should the widget update?
  • Every 15 minutes (minimum practical interval)
  • Every 30 minutes
  • Every hour (recommended default)
  • A few times per day
  • Based on specific times (e.g., calendar events)
  • On-demand from the main app via WidgetCenter.shared.reloadTimelines(ofKind:)

Generation Process

Step 1: Determine File Locations

Check project structure:

  • If a widget extension target directory exists, add view and provider files there
  • Otherwise, instruct user to create a Widget Extension target first

For widget extension files:

  • Place inside the existing widget extension directory (e.g., MyAppWidgets/)

For shared data models (if using App Groups):

  • If Sources/ or Shared/ exists --> place there
  • Otherwise --> create alongside existing models

Step 2: Create Core Files

Generate these files based on configuration answers:

  1. {Name}Widget.swift -- Widget definition with configuration
  • Widget struct with StaticConfiguration or AppIntentConfiguration
  • Supported families declaration
  • Display name and description
  1. {Name}TimelineProvider.swift -- Timeline logic
  • TimelineProvider (static) or AppIntentTimelineProvider (configurable)
  • Placeholder, snapshot, and timeline methods
  1. {Name}Entry.swift -- Timeline entry model
  • TimelineEntry struct with date and display data
  1. {Name}WidgetViews.swift -- Size-specific views
  • Separate view struct for each supported family
  • Uses containerBackground for iOS 17+ removable backgrounds
  1. {Name}AppIntent.swift (if interactive or configurable)
  • WidgetConfigurationIntent for configurable widgets
  • AppIntent for interactive widget buttons/toggles
  1. WidgetBundle update -- Register the new widget
  • Add to existing bundle or create new one

Step 3: Generate Code from Templates

Use the templates in templates.md and customize based on user answers:

  • Replace placeholder names with the actual widget name
  • Configure supported families based on size selection
  • Include or exclude interactive elements
  • Include or exclude lock screen accessory views
  • Set up App Group shared data access if needed
  • Configure timeline refresh policy based on update frequency

Widget Design Rules (WWDC20)

Apply these when generating the size-specific views. A good widget idea is at least one of personal (the user's own data), informational (the most-wanted status at a glance), or contextual (the right thing for this moment). Glanceability is the bar — a widget is read in about a second on the way somewhere else.

| Rule | Specific |

|------|----------|

| Small widget | Max ~4 pieces of information; exactly one tap target (the whole widget) |

| Medium/Large | Multiple tap targets allowed — cell style for visually contained targets, content style for uncontained lists |

| Margins | 16pt default; 11pt acceptable for tighter graphical shapes (circles, glyphs) |

| Corners | Inner shapes must be concentric with the widget's corner radius |

| Layouts | Design each family separately — never scale the small layout up to medium/large |

| Typography | SF Pro, SF Pro Rounded, or SF Mono; custom fonts only when core to the brand |

| Logo | Only if the app aggregates content from multiple sources — and always top-right |

| Text bans | ❌ Instructional text ("tap to refresh") · ❌ "last updated/checked" language |

| Appearance | Support both light and dark |

| Placeholder | Ship a placeholder state (blocked shapes where content will be) for pre-data loading |

  • Support configuration where content is choosable (location, stock symbol, list) and design for the multiple-widgets pattern — users add several instances configured differently.
  • Smart Stack rotates to the most relevant widget — supply relevance metadata (TimelineEntryRelevance) so yours surfaces at the right moment.

Output Format

After generation, provide:

Files Created

MyAppWidgets/
├── {Name}Widget.swift              # Widget definition + configuration
├── {Name}TimelineProvider.swift     # Timeline provider with placeholder/snapshot/timeline
├── {Name}Entry.swift               # TimelineEntry data model
├── {Name}WidgetViews.swift         # Size-specific views for each family
├── {Name}AppIntent.swift           # (if configurable/interactive) App Intent
└── (update WidgetBundle if needed)

Shared/
└── {Name}DataProvider.swift        # (if App Groups) Shared data access

Integration Steps

1. Add the widget extension target (if not present):

  • File > New > Target > Widget Extension
  • Choose "Include Configuration App Intent" if configurable
  • Ensure the widget extension embeds in the main app

2. Enable App Groups (if sharing data with the main app):

  • Select the main app target > Signing & Capabilities > + Capability > App Groups
  • Select the widget extension target > Signing & Capabilities > + Capability > App Groups
  • Use the same group identifier (e.g., group.com.yourcompany.yourapp)

3. Register the widget in the WidgetBundle:

@main
struct MyAppWidgets: WidgetBundle {
    var body: some Widget {
        // Existing widgets...
        {Name}Widget()
    }
}

4. Trigger widget updates from the main app when data changes:

import WidgetKit

// Reload a specific widget
WidgetCenter.shared.reloadTimelines(ofKind: "{Name}Widget")

// Or reload all widgets
WidgetCenter.shared.reloadAllTimelines()

5. For App Group data sharing, write from the main app:

let sharedDefaults = UserDefaults(suiteName: "group.com.yourcompany.yourapp")
sharedDefaults?.set(encodedData, forKey: "widgetData")

// Then trigger reload
WidgetCenter.shared.reloadTimelines(ofKind: "{Name}Widget")

Testing Instructions

  1. Simulator support: Widgets can be previewed in Xcode Canvas and tested in Simulator.
  2. Add to home screen: Long-press the home screen > tap "+" > find your app > select the widget size.
  3. Lock screen widgets: Long-press the lock screen > "Customize" > select the widget area.
  4. Preview in Xcode: Use #Preview with timeline entry data for rapid iteration.
  5. Timeline debugging: Use WidgetCenter.shared.getCurrentConfigurations to verify registered widgets.
  6. Interactive widget testing (iOS 17+): Tap buttons/toggles directly on the widget in Simulator or device.
  7. Memory profiling: Widgets have a 40MB memory limit. Profile in Instruments if loading images or large datasets.

Common Widget Patterns

Weather Widget

  • Data: Temperature, condition icon, hourly forecast
  • Sizes: systemSmall (current temp), systemMedium (hourly), accessoryCircular (temp gauge)
  • Update: Every 30 minutes via network API
  • Timeline: Generate entries for next few hours with forecast data

Calendar / Events Widget

  • Data: Upcoming events, times, locations
  • Sizes: systemSmall (next event), systemMedium (next 3 events), accessoryRectangular (next event)
  • Update: Based on event start times using .after(nextEventDate) policy
  • Timeline: One entry per upcoming event transition

Fitness / Health Widget

  • Data: Steps, calories, activity rings
  • Sizes: systemSmall (ring summary), accessoryCircular (ring gauge), accessoryRectangular (stats)
  • Update: Every 15-30 minutes from HealthKit via App Groups
  • Interactive: None (read-only data display)

Quick Actions Widget

  • Data: Action buttons (start timer, toggle light, log water)
  • Sizes: systemSmall (single action), systemMedium (2-4 actions)
  • Update: Infrequent (actions are static, only state changes)
  • Interactive: Button(intent:) for each action (iOS 17+)

Countdown Widget

  • Data: Target date, label, time remaining
  • Sizes: systemSmall (days remaining), accessoryCircular (days number), accessoryInline (text countdown)
  • Update: Daily or use Text(date, style: .timer) / Text(date, style: .relative) for automatic live updates
  • Timeline: SwiftUI date styles update automatically without timeline refreshes

Gotchas and Limits

  • Timeline budget: The system limits how often your timeline provider runs. Typically ~40-70 refreshes per day. Do not rely on exact timing.
  • 40MB memory limit: Widget extensions are killed if they exceed 40MB. Avoid loading large images or datasets. Use thumbnails and minimal data.
  • containerBackground required (iOS 17+): All widget views must use .containerBackground(for: .widget) to support the system's removable background feature. Without this, widgets show a default placeholder background.
  • Accessory family rendering: Lock screen widgets render in a limited color space. Use AccessoryWidgetBackground() for backgrounds and keep designs simple with high contrast.
  • No animation: Widgets do not support explicit animations. Use Text(date, style: .timer) for countdowns; the system animates these for you.
  • No scrolling: Widgets cannot scroll. Design for fixed, visible content.
  • No video or maps: MapKit and AVKit are not available in widget extensions.
  • Networking in timeline provider: Network requests in getTimeline must complete quickly. The system may terminate long-running providers.
  • @main conflict: Only one @main per widget extension. If you have multiple widgets, use a WidgetBundle as the single @main entry point.
  • Configurable widget data persistence: AppIntent parameter values are stored by the system. Do not rely on UserDefaults for configuration state.
  • Xcode previews: Use #Preview(as: .systemSmall) for family-specific widget previews.
  • Shared code with main app: Timeline entries and data models referenced by both targets must have target membership in both the main app and the widget extension.

References

想直接用这个技能?

本站把开放许可(MIT / Apache 等)的技能按仓库打包整理到网盘,点一下转存到你自己的网盘,不用一个个从 GitHub 拉。许可未声明的技能只给原始仓库链接,不打包。