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 の各プラットフォームで一目でわかり、タイムリーな体験を構築します。

クイックスタート

ウィジェット拡張機能を作成する
  1. File → New → Target → Widget Extension
  2. 静的ウィジェットの場合は、「Include Live Activity」と「Include Configuration App Intent」の選択を解除します
  3. ウィジェットには Widget プロトコル、TimelineProvider、SwiftUI ビューが必要です
最小限のウィジェット構造
@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
}

ウィジェットファミリーとサイズ

ファミリープラットフォーム用途
systemSmalliOS、iPadOS、macOS、visionOS単一のタップ対象、一目でわかる情報
systemMediumiOS、iPadOS、macOS、visionOS複数のデータポイント、インタラクティブな要素
systemLargeiOS、iPadOS、macOS、visionOS豊富なコンテンツ、複数のインタラクション
systemExtraLargeiPadOS、macOS、visionOSダッシュボード形式のレイアウト
accessoryCirculariOS ロック画面、watchOS最小限の情報、ゲージ形式
accessoryRectangulariOS ロック画面、watchOS2~3 行のテキスト
accessoryInlineiOS ロック画面、watchOS1 行のテキスト+任意の画像
accessoryCornerwatchOS のみコーナーコンプリケーション
ウィジェットファミリーに合わせる
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()
        }
    }
}

レンダリングモード

ウィジェットはコンテキストに応じて異なる方法でレンダリングされます。

モード使用時動作
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ライブアクティビティ

リファレンスドキュメント

主な制約

  • リアルタイム更新は不可:タイムラインを使用します。システムは更新をまとめて処理します
  • 予算に制限あり:使用状況に応じて 1 日あたり約 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"
)
ウィジェットを強制的に更新する
import WidgetKit
WidgetCenter.shared.reloadTimelines(ofKind: "com.app.mywidget")
WidgetCenter.shared.reloadAllTimelines()
機密コンテンツのプレースホルダー
.privacySensitive() // Redacts when device locked

コメント