Setting SwiftUI Library

repository·main·Indexed 23 days ago

https://github.com/aheze/setting

A SwiftUI library for creating searchable preference panels using a result-builder-based syntax. It provides components like SettingStack, SettingPage, and SettingGroup, along with built-in controls such as SettingToggle, SettingSlider, and SettingPicker. Supports custom views via SettingCustomView and reusable segments using @SettingBuilder. Requires iOS 15+ or macOS Monterey and up.

Tokens
1.9K
Snippets
7
Records
7
Agent score
32%

What's inside Setting

  1. How to build a settings interface with SettingStack

    main

    To create a settings interface, start with a SettingStack. Inside the stack, use SettingPage to define pages. You can nest SettingPage components inside each other to create hierarchical navigation. Use SettingGroup to organize components within a page. The syntax is powered by result builders, allowing for a declarative structure.

    import Setting
    import SwiftUI
    
    struct PlaygroundView: View {
        @AppStorage("isOn") var isOn = true
    
        var body: some View {
            SettingStack {
                SettingPage(title: "Playground") {
                    SettingGroup(header: "Main Group") {
                        SettingToggle(title: "This value is persisted!", isOn: $isOn)
    
                        SettingCustomView {
                            Image("Logo")
                                .resizable()
                                .aspectRatio(contentMode: .fit)
                                .frame(width: 160)
                                .padding(20)
                        }
    
                        SettingPage(title: "Advanced Settings") {
                            SettingText(title: "I show up on the next page!")
                        }
                    }
                }
            }
        }
    }
  2. Use pre-made components: Toggle, Slider, and Picker

    main

    Setting provides several built-in components that integrate with SwiftUI state management (@State, @AppStorage, @Published, etc.):

    • SettingToggle(title:isOn:): A toggle switch.
    • SettingSlider(value:range:): A slider for numeric values.
    • SettingPicker(title:choices:selectedIndex:choicesConfiguration:): A picker. You can customize the display mode using choicesConfiguration (e.g., .menu).
    // Toggle
    SettingToggle(title: "On", isOn: $isOn)
    
    // Slider
    SettingSlider(value: $value, range: 0 ... 10)
    
    // Picker
    SettingPicker(
        title: "Picker",
        choices: ["A", "B", "C", "D"],
        selectedIndex: $index
    )
    
    // Picker with menu mode
    SettingPicker(
        title: "Picker with menu",
        choices: ["A", "B", "C", "D"],
        selectedIndex: $index,
        choicesConfiguration: .init(pickerDisplayMode: .menu)
    )
  3. Customize search results with SettingViewModel

    main

    You can provide a custom SettingViewModel to SettingStack for finer control over the search functionality. This allows you to define a custom customNoResultsView to show when a user's search query returns no matches.

    struct PlaygroundView: View {
        @StateObject var settingViewModel = SettingViewModel()
    
        var body: some View {
            SettingStack(settingViewModel: settingViewModel) {
                SettingPage(title: "Playground") {
                    SettingGroup {
                        SettingText(title: "Welcome to Setting!")
                    }
                } customNoResultsView: {
                    VStack(spacing: 20) {
                        Image(systemName: "xmark")
                            .font(.largeTitle)
    
                        Text("No results for '\(settingViewModel.searchText)'")
                    }
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                }
            }
        }
    }
  4. Add custom SwiftUI views with SettingCustomView

    main

    If the pre-made components do not meet your needs, you can wrap any standard SwiftUI view inside a SettingCustomView to include it in your settings layout.

    SettingCustomView {
        Color.blue
            .opacity(0.1)
            .cornerRadius(12)
            .overlay {
                Text("Put anything here!")
                    .foregroundColor(.blue)
                    .font(.title.bold())
            }
            .frame(height: 150)
            .padding(.horizontal, 16)
    }
  5. Organize settings using @SettingBuilder

    main

    To split a large settings interface into multiple variables or files, use the @SettingBuilder attribute. This allows you to define reusable segments of your settings hierarchy.

    struct ContentView: View {
        var body: some View {
            SettingStack {
                SettingPage(title: "Settings") {
                    general
                    misc
                }
            }
        }
        
        @SettingBuilder var general: some Setting {
            SettingPage(title: "General") {
                SettingText(title: "General Settings")
            }
        }
        
        @SettingBuilder var misc: some Setting {
            SettingPage(title: "Misc") {
                SettingText(title: "Misc Settings")
            }
        }
    }
  6. Handle duplicate titles with the id parameter

    main

    If your settings contain multiple components with the same title, use the id parameter to ensure they are rendered correctly and uniquely.

    SettingText(id: "Announcement 1", title: "Hello!")
    SettingText(id: "Announcement 2", title: "Hello!")