mcpField
S
swift-settingskit

swift-settingskit

github.com/secondsky设计与 UI240122 次安装5 周前更新
代码仓库

关于 swift-settingskit

Swift SettingsKit 是用于 Apple 平台 SwiftUI 应用的设置界面 Swift 包。它将控件组织为可搜索的分组,并根据设备调整导航和呈现方式。

主要功能

  1. 01设置分组与控件
  2. 02内置设置搜索
  3. 03侧边栏与单列样式
  4. 04嵌套设置层级
  5. 05响应式 @Observable 模型绑定
  6. 06适配平台的界面呈现

适用场景

  1. 01构建可搜索的应用设置界面
  2. 02将设置整理为嵌套分区
  3. 03在不同 Apple 设备上呈现设置
  4. 04根据功能标志显示条件设置

安装

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

$npx skills add https://github.com/secondsky/claude-skills --skill swift-settingskit

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

包含的文件

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

assets/
basic-settings-template.swift
custom-style-template.swift
demo-app-template.swift
modular-settings-template.swift
references/
advanced-patterns.md
api-reference.md
performance-edge-cases.md
search-implementation.md
styling-guide.md

详细介绍

Swift SettingsKit

状态:已可用于生产环境 ✅ 最后更新:2025-11-23 依赖项:无(独立 Swift 包) 最新版本:SettingsKit 1.0.0+

支持的工具链

最低要求:

  • Swift:6.0+(@Observable 宏和 SettingsKit 编译所必需)
  • Xcode:16.0+(提供 Swift 6.0 工具链)
  • 平台:iOS 17.0+ / macOS 14.0+ / watchOS 10.0+ / tvOS 17.0+ / visionOS 1.0+

注意:虽然 @Observable 在 Swift 5.9 中引入,但 SettingsKit 的 Package.swift 将 Swift 6.0+ 指定为最低工具链版本。本技能中的所有示例都面向 Swift 6.0+。


快速开始(5 分钟)

1. 添加 SettingsKit 包

通过 Xcode 将 Swift 包添加到项目中:

// File → Add Package Dependencies
// Enter: https://github.com/aeastr/SettingsKit.git
// Version: 1.0.0 or later

或通过 Package.swift 添加:

dependencies: [
    .package(url: "https://github.com/aeastr/SettingsKit.git", from: "1.0.0")
]

这很重要,原因如下:

  • SettingsKit 需要 iOS 17+ / macOS 14+ 才能使用现代 SwiftUI 功能
  • 使用 @Observable 宏需要 Swift 6.0+
  • 框架可在所有 Apple 平台上自适应
2. 创建可观察的设置模型
import SwiftUI
import SettingsKit

@Observable
class AppSettings {
    var notificationsEnabled = true
    var darkMode = false
    var username = "Guest"
    var fontSize: Double = 14.0
}

重要:

  • 使用 @Observable 宏(不要使用 @Published 或 ObservableObject)
  • SettingsKit 专为 Swift 的现代观察系统设计
  • 设置模型必须位于 SwiftUI 环境中才能进行绑定
3. 实现 SettingsContainer 协议
struct MySettings: SettingsContainer {
    @Environment(AppSettings.self) var appSettings

    var settingsBody: some SettingsContent {
        @Bindable var settings = appSettings

        SettingsGroup("General", systemImage: "gear") {
            SettingsItem("Notifications") {
                Toggle("Enable", isOn: $settings.notificationsEnabled)
            }

            SettingsItem("Dark Mode") {
                Toggle("Enable", isOn: $settings.darkMode)
            }
        }

        SettingsGroup("Profile", systemImage: "person") {
            SettingsItem("Username") {
                TextField("Username", text: $settings.username)
            }

            SettingsItem("Font Size") {
                Slider(value: $settings.fontSize, in: 10...24)
                Text("\(Int(settings.fontSize))pt")
            }
        }
    }
}

重要:

  • 必须使用 @Bindable 包装器,从 @Observable 模型创建绑定
  • settingsBody 返回 SettingsContent(而非 View)
  • 在侧边栏样式中,分组会显示为导航链接(可点击的行)
4. 添加到应用
import SwiftUI
import SettingsKit

@main
struct MyApp: App {
    @State private var settings = AppSettings()

    var body: some Scene {
        WindowGroup {
            MySettings()
                .environment(settings)
        }
    }
}

**结果:**完整的设置界面,包含:

  • 自动导航(iPad/Mac 上显示侧边栏,iPhone 上显示单列)
  • 内置搜索功能
  • 自适应平台的呈现方式
  • 响应式状态更新

4 步设置流程

步骤 1:安装包依赖项

在 Xcode 中通过 Swift Package Manager 添加 SettingsKit:

  1. File → Add Package Dependencies
  2. 输入仓库 URL:https://github.com/aeastr/SettingsKit.git
  3. 在 "1.0.0" 中选择 "Up to Next Major Version"
  4. 添加到应用目标

要点:

  • 需要 Xcode 16.0+ 才能支持 Swift 6.0
  • 包含所有平台(iOS、macOS、watchOS、tvOS、visionOS)
  • 无需额外配置
步骤 2:定义设置数据模型

创建一个 @Observable 类来保存设置状态:

import SwiftUI

@Observable
class AppSettings {
    // General settings
    var notificationsEnabled = true
    var soundEnabled = true
    var hapticFeedback = true

    // Appearance settings
    var darkMode = false
    var accentColor: Color = .blue
    var fontSize: Double = 16.0

    // User profile
    var username = ""
    var email = ""
    var profileImageURL: URL?
}

要点:

  • 使用 @Observable 宏(Swift 6.0+)实现现代观察
  • 使用默认值初始化所有属性
  • 将设置模型与视图逻辑分离
  • 可以包含用于派生状态的计算属性
步骤 3:构建设置层级结构

实现 SettingsContainer 协议以定义设置界面:

import SettingsKit

struct MySettings: SettingsContainer {
    @Environment(AppSettings.self) var appSettings

    var settingsBody: some SettingsContent {
        @Bindable var settings = appSettings

        // Navigation group (tappable row)
        SettingsGroup("General", systemImage: "gear") {
            SettingsItem("Notifications") {
                Toggle("Enable", isOn: $settings.notificationsEnabled)
            }
            SettingsItem("Sound Effects") {
                Toggle("Enable", isOn: $settings.soundEnabled)
            }
        }
        .settingsTags(["notifications", "sounds", "alerts"])

        // Inline group (section header)
        SettingsGroup("Quick Settings", .inline) {
            SettingsItem("Dark Mode") {
                Toggle("Enable", isOn: $settings.darkMode)
            }
        }

        // Nested navigation
        SettingsGroup("Profile", systemImage: "person") {
            SettingsGroup("Account", systemImage: "person.circle") {
                SettingsItem("Username") {
                    TextField("Username", text: $settings.username)
                }
                SettingsItem("Email") {
                    TextField("Email", text: $settings.email)
                }
            }
        }
    }
}

要点:

  • SettingsGroup 创建导航链接(默认行为)或分区标题(.inline)
  • SettingsItem 用于封装单个控件
  • 添加 .settingsTags([...]) 以提升搜索可发现性
  • 分组可无限嵌套,构建深层层级结构
步骤 4:配置呈现样式

选择设置的显示方式:

// Sidebar style (default) - Split view on iPad/Mac
MySettings(settings: settings)
    .settingsStyle(.sidebar)

// Single column style - Clean list on all platforms
MySettings(settings: settings)
    .settingsStyle(.single)

// Custom style - Full control over appearance
MySettings(settings: settings)
    .settingsStyle(MyCustomStyle())

要点:

  • .sidebar:使用基于选择的导航的 NavigationSplitView(默认)
  • .single:使用推送导航的单个 NavigationStack
  • 自定义样式需遵循 SettingsStyle 协议
  • 平台会根据设备环境自动调整

重要规则

始终遵循

✅ 设置模型使用 @Observable - SettingsKit 的响应式系统所必需
✅ 使用 @Bindable 包装环境设置 - 在 settingsBody 中启用双向绑定
✅ 为重要分组添加可搜索标签 - 通过 .settingsTags([...]) 提升可发现性
✅ 将设置模型放在 SwiftUI 环境中 - 在父视图上使用 .environment(settings)
✅ 所有可交互控件都使用 SettingsItem - 确保正确建立搜索索引

切勿执行

❌ 切勿将 ObservableObject 与 @Published 搭配使用 - SettingsKit 要求使用现代的 @Observable ❌ 切勿在没有 @Bindable 包装器的情况下创建绑定 - 会导致编译错误 ❌ 切勿在 settingsBody 中进行大量计算 - 每次渲染都会重新计算,应保持轻量 ❌ 切勿忘记将设置注入环境 - 会导致运行时崩溃 ❌ 简单控件切勿使用 CustomSettingsGroup - 这会不必要地绕过搜索索引


防止已知问题

此技能可防止 5 个已记录的问题:

问题 #1:“Cannot convert value of type 'Binding' to expected argument type 'Binding'”

错误:尝试在没有 @Bindable 包装器的情况下绑定到 @Observable 属性时出现编译错误 来源:Swift 并发迁移指南、Observable 宏文档 原因:与 @Published 属性不同,@Observable 模型需要 @Bindable 包装器来创建绑定 预防措施:创建绑定之前,始终先在 settingsBody 中使用 @Bindable var settings = appSettings

问题 #2:模型更改时设置 UI 不更新

错误:开关、滑块和文本框无法反映模型更改 来源:SettingsKit GitHub issues、SwiftUI 观察系统文档 原因:设置模型未正确注入 SwiftUI 环境,导致观察失效 预防措施:在父视图上使用 .environment(settings),并在 SettingsContainer 中使用 @Environment(AppSettings.self)

问题 #3:侧边栏样式中的导航状态冲突

错误:选择设置项后无法导航,或导航栈损坏 来源:SettingsKit 架构文档、NavigationSplitView 最佳实践 原因:侧边栏样式中直接使用 NavigationLink 而非 SettingsGroup 会导致状态冲突 预防措施:导航时始终使用 SettingsGroup(切勿使用原始的 NavigationLink),让 SettingsKit 管理导航状态

问题 #4:自定义分组未出现在搜索结果中

错误:搜索功能无法检索 CustomSettingsGroup 内容 来源:SettingsKit README——“可按标题、图标和标签搜索自定义分组,但内容渲染时不会对元素建立索引” 原因:CustomSettingsGroup 为提供完整的 UI 控制权而绕过标准索引,只有元数据可搜索 预防措施:可搜索的内容使用常规 SettingsGroup/SettingsItem;CustomSettingsGroup 留作复杂的自定义 UI 使用

问题 #5:macOS 上设置崩溃,并出现“Nil coalescing”运行时错误

错误:在 macOS 上打开设置时,因基于目标的导航问题导致应用崩溃 来源:SettingsKit macOS 专用实现说明 原因:macOS 使用基于目标的 NavigationLink(而非基于选择的方式)来避免控件更新问题,但这要求正确设置导航状态 预防措施:让 SettingsKit 负责创建导航栈;在 macOS 上不要将 SettingsContainer 包装在自定义 NavigationStack 中


配置文件参考

Package.swift(完整示例)
// swift-tools-version: 6.0
import PackageDescription

let package = Package(
    name: "MyApp",
    platforms: [
        .iOS(.v17),
        .macOS(.v14),
        .watchOS(.v10),
        .tvOS(.v17),
        .visionOS(.v1)
    ],
    products: [
        .executable(name: "MyApp", targets: ["MyApp"])
    ],
    dependencies: [
        .package(url: "https://github.com/aeastr/SettingsKit.git", from: "1.0.0")
    ],
    targets: [
        .executableTarget(
            name: "MyApp",
            dependencies: [
                .product(name: "SettingsKit", package: "SettingsKit")
            ]
        )
    ]
)

这些设置的原因:

  • 平台版本符合 SettingsKit 的最低要求(iOS 17+ 等)
  • 使用 @Observable 宏需要 Swift tools 版本 6.0+
  • SettingsKit 已通过语义化版本控制作为软件包依赖项添加

常见模式

模式 1:模块化设置分组

将复杂的设置部分提取为单独的 SettingsContent 类型,以便更好地组织:

struct NotificationSettings: SettingsContent {
    @Bindable var settings: AppSettings

    var body: some SettingsContent {
        SettingsGroup("Notifications", systemImage: "bell") {
            SettingsItem("Enable Notifications") {
                Toggle("Enable", isOn: $settings.notificationsEnabled)
            }

            if settings.notificationsEnabled {
                SettingsItem("Sound") {
                    Toggle("Enable", isOn: $settings.soundEnabled)
                }
                SettingsItem("Badge") {
                    Toggle("Show badge", isOn: $settings.badgeEnabled)
                }
            }
        }
        .settingsTags(["notifications", "alerts", "sounds", "badges"])
    }
}

// Use in main settings:
var settingsBody: some SettingsContent {
    NotificationSettings(settings: settings)
    AppearanceSettings(settings: settings)
    PrivacySettings(settings: settings)
}

适用场景:包含 5 个以上分组的复杂设置层级、条件内容,或团队成员需要协作处理不同部分

模式 2:可搜索的自定义开发者工具

使用 CustomSettingsGroup 构建高级 UI,同时保持可搜索性:

CustomSettingsGroup("Developer Tools", systemImage: "hammer") {
    VStack(spacing: 20) {
        GroupBox("Debug Information") {
            VStack(alignment: .leading, spacing: 8) {
                Text("App Version: 1.0.0")
                Text("Build: 42")
                Text("Environment: Production")
            }
            .frame(maxWidth: .infinity, alignment: .leading)
        }

        Button("Clear Cache") {
            clearCache()
        }
        .buttonStyle(.borderedProminent)

        Button("Export Logs", systemImage: "square.and.arrow.up") {
            exportLogs()
        }
    }
    .padding()
}
.settingsTags(["debug", "testing", "logs", "advanced"])

适用场景:不符合标准 SettingsItem 模式的复杂自定义 UI,但仍需通过标签确保可被搜索发现

模式 3:条件设置可见性

根据功能标志或用户权限显示/隐藏设置:

SettingsGroup("Advanced", systemImage: "gearshape.2") {
    SettingsItem("Enable Advanced Features") {
        Toggle("Enable", isOn: $settings.showAdvanced)
    }

    if settings.showAdvanced {
        SettingsItem("Beta Features") {
            Toggle("Enable", isOn: $settings.betaFeaturesEnabled)
        }

        SettingsItem("Developer Mode") {
            Toggle("Enable", isOn: $settings.developerMode)
        }
    }

    if settings.developerMode {
        SettingsGroup("Developer Options", systemImage: "wrench.and.screwdriver") {
            SettingsItem("Verbose Logging") {
                Toggle("Enable", isOn: $settings.verboseLogging)
            }
        }
    }
}

适用场景:功能标志、用户权限级别、逐步展示复杂内容

模式 4:所有控件类型

SettingsItem 支持所有标准 SwiftUI 控件:

SettingsGroup("All Controls", systemImage: "slider.horizontal.3") {
    // Toggle (Boolean)
    SettingsItem("Enable Feature") {
        Toggle("Enable", isOn: $settings.featureEnabled)
    }

    // Slider (Continuous value)
    SettingsItem("Volume") {
        VStack(alignment: .leading, spacing: 8) {
            Slider(value: $settings.volume, in: 0...100)
            Text("\(Int(settings.volume))%")
                .font(.caption)
                .foregroundStyle(.secondary)
        }
    }

    // TextField (Text input)
    SettingsItem("Username") {
        TextField("Enter username", text: $settings.username)
            .textFieldStyle(.roundedBorder)
    }

    // Picker (Selection)
    SettingsItem("Theme") {
        Picker("", selection: $settings.theme) {
            Text("Light").tag(Theme.light)
            Text("Dark").tag(Theme.dark)
            Text("Auto").tag(Theme.auto)
        }
        .pickerStyle(.segmented)
    }

    // Stepper (Increment/Decrement)
    SettingsItem("Font Size") {
        Stepper("\(Int(settings.fontSize)) pt", value: $settings.fontSize, in: 10...24)
    }

    // Button (Action)
    SettingsItem("Reset Settings") {
        Button("Reset") {
            resetSettings()
        }
        .buttonStyle(.borderedProminent)
        .tint(.red)
    }

    // ColorPicker (Color selection)
    SettingsItem("Accent Color") {
        ColorPicker("Choose color", selection: $settings.accentColor)
    }

    // DatePicker (Date/Time selection)
    SettingsItem("Reminder Time") {
        DatePicker("", selection: $settings.reminderTime, displayedComponents: .hourAndMinute)
    }
}

适用场景:构建设置时,用作可用控件的参考


何时加载参考资料

针对特定主题的详细文档,请加载其他参考文件:

  • 实现高级 SettingsContainer 自定义、创建自定义 SettingsContent 类型,或需要所有协议和修饰符的详细 API 文档时,加载 references/api-reference.md

  • 自定义设置外观、实现自定义 SettingsStyle,或需要平台专属样式指南时,加载 references/styling-guide.md

  • 实现自定义搜索逻辑、调试搜索行为,或需要了解 SettingsKit 搜索架构时,加载 references/search-implementation.md

  • 构建复杂的嵌套层级、实现动态设置、处理持久化,或需要可用于生产环境的架构模式时,加载 references/advanced-patterns.md

  • 构建大型设置层级(100 个以上分组或 1000 个以上项目)、遇到性能问题,或需要压力测试指南和优化策略时,加载 references/performance-edge-cases.md


使用捆绑资源

脚本(scripts/)

不包含脚本——SettingsKit 是纯 Swift 软件包,无需构建脚本。

参考资料(references/)

高级主题的详细文档文件:

  • references/api-reference.md - SettingsKit 所有协议、类型和修饰符的完整 API 文档
  • references/styling-guide.md - 自定义设置外观和平台专属行为的综合指南
  • references/search-implementation.md - 深入讲解搜索架构、自定义搜索实现和搜索评分
  • references/advanced-patterns.md - 针对复杂层级、状态管理、持久化和测试的生产环境模式
  • references/performance-edge-cases.md - 性能优化、压力测试和大型层级处理

何时加载:请参阅上方的“何时加载参考资料”部分,了解具体场景

资源文件(assets/)

用于快速设置的 Swift 模板文件:

  • assets/basic-settings-template.swift - 完整的最简设置实现
  • assets/custom-style-template.swift - 自定义 SettingsStyle 实现模板(5 个示例)
  • assets/modular-settings-template.swift - 多文件设置组织模式
  • assets/demo-app-template.swift - 完整的演示应用,与官方 SettingsKit 演示一致(25 个以上属性、所有控件类型、压力测试)

依赖项

必需:

  • Swift 6.0+(支持 @Observable 宏)
  • iOS 17.0+ / macOS 14.0+ / watchOS 10.0+ / tvOS 17.0+ / visionOS 1.0+
  • SwiftUI 框架(内置)

可选:

  • 无——SettingsKit 是独立框架,没有外部依赖项

官方文档


软件包版本(已于 2025-11-23 验证)

{
  "dependencies": {
    "SettingsKit": "1.0.0"
  }
}

平台要求:

  • iOS 17.0+
  • macOS 14.0+
  • watchOS 10.0+
  • tvOS 17.0+
  • visionOS 1.0+
  • Swift 6.0+
  • Xcode 16.0+

生产环境示例

此技能基于官方 SettingsKit 仓库和示例:

  • 仓库:https://github.com/Aeastr/SettingsKit
  • 许可证:MIT
  • 验证:✅ 已在 iOS 17+、macOS 14+、watchOS 10+、tvOS 17+、visionOS 1+ 上测试
  • 架构:用于可搜索且具备响应性的设置的混合元数据/视图/渲染系统

故障排除

问题:“Cannot find 'SettingsContainer' in scope”

解决方案:在文件顶部导入 SettingsKit:import SettingsKit。请确认已在 Xcode 项目设置中将该软件包添加到目标依赖项。

问题:模型更改时,设置开关不会更新

解决方案:确保设置模型位于 SwiftUI 环境中(.environment(settings)),并在创建绑定之前,在 settingsBody 中使用 @Bindable 包装器。

问题:侧边栏样式下无法导航

解决方案:确认使用的是 SettingsGroup(而不是原始 NavigationLink),且没有将 SettingsContainer 包装在自定义 NavigationStack/NavigationSplitView 中。

问题:搜索无法找到我的自定义设置

解决方案:为包含相关关键词的组添加 .settingsTags([...])。CustomSettingsGroup 内容不会被索引——请使用 SettingsItem 来创建可搜索的控件。


完整设置检查清单

使用此检查清单验证你的设置:

  • 已通过 Swift Package Manager 添加 SettingsKit 软件包(1.0.0+)
  • 满足最低平台版本要求(iOS 17+ / macOS 14+ / Swift 6.0+)
  • 设置模型使用 @Observable(而非 ObservableObject)
  • 已实现包含 settingsBody 的 SettingsContainer 协议
  • 创建绑定之前使用了 @Bindable 包装器
  • 已将设置模型注入环境(.environment(settings))
  • 设置组使用 .settingsTags([...]) 进行搜索
  • 应用编译无错误
  • 设置界面在目标平台上显示正常
  • 搜索功能正常(尝试搜索已标记的关键词)
  • 设置状态会持久保存并实时更新

有问题?遇到故障?

  1. 查看 references/api-reference.md,了解详细的 API 文档
  2. 查看 references/advanced-patterns.md,了解复杂场景
  3. 核对 4 步设置流程中的所有步骤
  4. 查看官方仓库:https://github.com/Aeastr/SettingsKit
  5. 确保满足 Swift 6.0+ 和 iOS 17+ / macOS 14+ 的要求

评论

支持 Markdown