SwiftSettingsKit(Swift设置工具包) swift-settingskit

这是一个用于 SwiftUI 的 SettingsKit 库,专为构建设置和偏好界面设计。它支持搜索功能、嵌套导航、@Observable/@Bindable 状态管理,适用于 iOS、macOS、watchOS、tvOS 和 visionOS 平台。关键词:SettingsKit, SwiftUI, 设置界面, 搜索功能, 导航, 状态管理, 移动开发, 软件开发。

移动开发 0 次安装 0 次浏览 更新于 3/7/2026

名称: swift-settingskit 描述: 适用于 SwiftUI 设置界面的 SettingsKit(iOS, macOS, watchOS, tvOS, visionOS)。用于设置/偏好屏幕、可搜索设置、嵌套导航、@Observable/@Bindable 状态,或遇到设置更新错误、导航状态问题。

关键词: SettingsKit, SwiftUI 设置, 设置界面, 偏好 UI, 可搜索设置, 设置导航, SettingsContainer, SettingsGroup, SettingsItem, CustomSettingsGroup, 设置标签, 设置搜索, Observable 设置, Bindable 设置, iOS 17, macOS 14, Swift 6, 设置样式, 侧边栏设置, 声明式设置, 设置层次结构 许可证: MIT

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 包添加到您的项目:

// 文件 → 添加包依赖
// 输入: https://github.com/aeastr/SettingsKit.git
// 版本: 1.0.0 或更高

或通过 Package.swift:

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

为什么重要:

  • SettingsKit 需要 iOS 17+ / macOS 14+ 以支持现代 SwiftUI 功能
  • Swift 6.0+ 需要支持 @Observable 宏
  • 框架在所有苹果平台上自适应

2. 创建 Observable 设置模型

import SwiftUI
import SettingsKit

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

关键:

  • 使用 @Observable 宏(而不是 @PublishedObservableObject
  • 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 上的单列)
  • 内置搜索功能
  • 平台自适应呈现
  • 响应式状态更新

四步设置过程

步骤 1: 安装包依赖

通过 Xcode 中的 Swift 包管理器添加 SettingsKit:

  1. 文件 → 添加包依赖
  2. 输入仓库 URL:https://github.com/aeastr/SettingsKit.git
  3. 选择“从 1.0.0 起的最新主要版本”
  4. 添加到您的应用目标

关键点:

  • 需要 Xcode 16.0+ 以支持 Swift 6.0
  • 包包含所有平台(iOS、macOS、watchOS、tvOS、visionOS)
  • 无需额外配置

步骤 2: 定义设置数据模型

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

import SwiftUI

@Observable
class AppSettings {
    // 通用设置
    var notificationsEnabled = true
    var soundEnabled = true
    var hapticFeedback = true

    // 外观设置
    var darkMode = false
    var accentColor: Color = .blue
    var fontSize: Double = 16.0

    // 用户资料
    var username = ""
    var email = ""
    var profileImageURL: URL?
}

关键点:

  • 使用 @Observable 宏(Swift 6.0+)进行现代观察
  • 初始化所有属性为默认值
  • 保持设置模型与视图逻辑分离
  • 可以包含计算属性以派生状态

步骤 3: 构建设置层次结构

实现 SettingsContainer 协议来定义您的设置 UI:

import SettingsKit

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("Sound Effects") {
                Toggle("Enable", isOn: $settings.soundEnabled)
            }
        }
        .settingsTags(["notifications", "sounds", "alerts"])

        // 内联组(节标题)
        SettingsGroup("Quick Settings", .inline) {
            SettingsItem("Dark Mode") {
                Toggle("Enable", isOn: $settings.darkMode)
            }
        }

        // 嵌套导航
        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: 配置呈现样式

选择如何显示设置:

// 侧边栏样式(默认)- iPad/Mac 上的拆分视图
MySettings(settings: settings)
    .settingsStyle(.sidebar)

// 单列样式 - 所有平台上的简洁列表
MySettings(settings: settings)
    .settingsStyle(.single)

// 自定义样式 - 对外观完全控制
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: “无法将类型 ‘Binding<T>’ 的值转换为期望的参数类型 ‘Binding<U>’”

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

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

错误: 切换开关、滑块和文本字段不反映模型更改 来源: SettingsKit GitHub 问题,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+ 等)
  • 需要 Swift 工具版本 6.0+ 以支持 @Observable 宏
  • 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"])
    }
}

// 在主设置中使用:
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(布尔值)
    SettingsItem("Enable Feature") {
        Toggle("Enable", isOn: $settings.featureEnabled)
    }

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

    // TextField(文本输入)
    SettingsItem("Username") {
        TextField("Enter username", text: $settings.username)
            .textFieldStyle(.roundedBorder)
    }

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

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

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

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

    // DatePicker(日期/时间选择)
    SettingsItem("Reminder Time") {
        DatePicker("", selection: $settings.reminderTime, displayedComponents: .hourAndMinute)
    }
}

何时使用: 构建设置时的控件可用性参考


何时加载参考文件

为特定主题加载额外的参考文件以获得详细文档:

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

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

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

  • 加载 references/advanced-patterns.md 当构建复杂嵌套层次结构、实现动态设置、处理持久性,或需要生产就绪的架构模式时

  • 加载 references/performance-edge-cases.md 当构建大型设置层次结构(100+ 组或 1000+ 项)、遇到性能问题,或需要压力测试指导和优化策略时


使用捆绑资源

脚本(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+ 上测试
  • 架构: 混合元数据/视图/渲染系统,用于可搜索 + 响应式设置

故障排除

问题: “找不到 ‘SettingsContainer’ 在作用域中”

解决方案: 在文件顶部导入 SettingsKit:import SettingsKit。在 Xcode 项目设置中验证包已添加到目标依赖。

问题: 模型更改时设置切换不更新

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

问题: 侧边栏样式中导航不工作

解决方案: 验证使用 SettingsGroup(而不是原始 NavigationLink),并且不要将 SettingsContainer 包装在自定义 NavigationStack/NavigationSplitView 中。

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

解决方案: 向组添加 .settingsTags([...]) 和相关的关键词。CustomSettingsGroup 内容未被索引——对可搜索控件使用 SettingsItem。


完整设置检查清单

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

  • [ ] SettingsKit 包已添加(1.0.0+)通过 Swift 包管理器
  • [ ] 满足最低平台版本(iOS 17+ / macOS 14+ / Swift 6.0+)
  • [ ] 设置模型使用 @Observable(而不是 ObservableObject)
  • [ ] SettingsContainer 协议已实现,带有 settingsBody
  • [ ] 在创建绑定之前使用了 @Bindable 包装器
  • [ ] 设置模型已注入环境(.environment(settings))
  • [ ] 设置组使用 .settingsTags([…]) 进行搜索
  • [ ] 应用编译无误
  • [ ] 设置 UI 在目标平台上正确显示
  • [ ] 搜索功能正常工作(尝试搜索带标签的关键词)
  • [ ] 设置状态持久并响应更新

问题?问题?

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