You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为SwiftUI应用设置偏好ColorScheme(亮色/暗色/系统)

解决SwiftUI中ColorScheme偏好设置无法跟随系统更新的问题

你的代码核心问题在于:当通过.preferredColorScheme(preferredDesign)手动指定颜色方案后,@Environment(\.colorScheme)获取到的是你设置的值,而非系统真实的颜色方案状态,所以onChange无法监听到系统模式的变化。

正确的做法是利用preferredColorScheme的可选特性:当传入nil时,应用会自动跟随系统的颜色方案,无需手动同步系统状态。下面是优化后的实现:

import SwiftUI

// 定义清晰的偏好枚举,替代原有的Int标记
enum ColorSchemePreference: CaseIterable {
    case system, light, dark
    
    var displayName: String {
        switch self {
        case .system: return "System"
        case .light: return "Hell"
        case .dark: return "Dunkel"
        }
    }
}

struct ContentView: View {
    // 存储用户的偏好选择
    @State private var selectedPreference: ColorSchemePreference = .system
    // 获取当前系统(或应用)的颜色方案,仅用于展示或其他逻辑
    @Environment(\.colorScheme) var currentColorScheme
    
    // 根据用户偏好返回对应的ColorScheme?,system模式返回nil让系统控制
    private var preferredColorScheme: ColorScheme? {
        switch selectedPreference {
        case .system: return nil
        case .light: return .light
        case .dark: return .dark
        }
    }
    
    var body: some View {
        VStack {
            Form {
                HStack {
                    Text("Design")
                        .frame(maxWidth: 100, alignment: .leading)
                    Spacer()
                    Picker("Design Picker", selection: $selectedPreference) {
                        ForEach(ColorSchemePreference.allCases, id: \.self) { preference in
                            Text(preference.displayName).tag(preference)
                        }
                    }
                    .pickerStyle(SegmentedPickerStyle())
                }
                .padding(.vertical, 13)
            }
            Divider()
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world! Current scheme: \(currentColorScheme == .light ? "Light" : "Dark")")
        }
        .padding()
        // 应用用户偏好的颜色方案,nil时跟随系统
        .preferredColorScheme(preferredColorScheme)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentView()
                .preferredColorScheme(.light)
            ContentView()
                .preferredColorScheme(.dark)
        }
    }
}

关键优化点:

  • 使用ColorSchemePreference枚举替代Int,让代码更易读、不易出错
  • 当用户选择"System"时,preferredColorScheme返回nil,此时应用会自动跟随系统的颜色变化,无需额外监听同步
  • 移除了冗余的systemDesign状态,简化了逻辑
  • 预览部分同时展示亮色和暗色模式的效果,方便调试

测试效果:

  1. 选择"System"后,切换系统的暗色模式,应用会自动切换对应的配色
  2. 选择"Hell"或"Dunkel"时,应用会固定在对应的模式,不受系统设置影响

内容的提问来源于stack exchange,提问作者neldierto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 05:54:54