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

SwiftUI Color转UIColor存入UserDefaults时转换后不等如何解决?

问题解答

为什么双向转换后Color实例不相等

SwiftUI 的 Color 并不是单纯存储RGBA数值的容器,它本质是 动态颜色描述符:你用到的 Color.orange 这类系统预设值,属于语义化动态颜色,内部还包含了适配暗黑模式、不同显示外观的规则,以及系统内置的类型标识。
当你转成 UIColor 再转回 Color 时,生成的是基于当前外观下RGBA数值的静态Color实例,和原来的语义化动态Color的内部属性不一致,所以 == 判断返回false是正常现象,并不存在颜色显示层面的信息丢失,两个实例实际渲染到界面上的效果完全一致。

正确存入UserDefaults的实现方案

根据你的需求可以选择以下两种方案:

方案1:存储固定RGBA值(适合自定义颜色、不需要动态适配的场景)

直接提取颜色的RGBA数值序列化存储,比NSKeyedArchiver更轻量稳定,扩展实现如下:

import SwiftUI
import UIKit

extension Color {
    // 转换为可存储的Data
    func toStorageData() -> Data? {
        guard let uiColorComponents = UIColor(self).cgColor.components, uiColorComponents.count >= 4 else { return nil }
        let rgba = [uiColorComponents[0], uiColorComponents[1], uiColorComponents[2], uiColorComponents[3]]
        return try? JSONEncoder().encode(rgba)
    }
    
    // 从存储的Data恢复Color
    static func fromStorageData(_ data: Data) -> Color? {
        guard let rgba = try? JSONDecoder().decode([CGFloat].self, from: data), rgba.count == 4 else { return nil }
        return Color(red: rgba[0], green: rgba[1], blue: rgba[2], opacity: rgba[3])
    }
}

使用示例:

// 存
if let colorData = Color.orange.toStorageData() {
    UserDefaults.standard.set(colorData, forKey: "user_custom_color")
}

// 读
if let savedData = UserDefaults.standard.data(forKey: "user_custom_color"), 
   let restoredColor = Color.fromStorageData(savedData) {
    // 直接使用恢复后的颜色即可
}

方案2:枚举映射存储(适合用系统预设动态颜色的场景)

如果需要保留系统颜色的动态适配特性(比如暗黑模式自动切换),不要直接存颜色实例,而是做一层枚举映射,存枚举的原始值:

enum PresetColor: String {
    case orange, blue, red, green
    // 把你需要用到的预设颜色都加进去
    
    var color: Color {
        switch self {
        case .orange: return .orange
        case .blue: return .blue
        case .red: return .red
        case .green: return .green
        }
    }
}

使用示例:

// 存
UserDefaults.standard.set(PresetColor.orange.rawValue, forKey: "user_selected_color")

// 读
if let rawValue = UserDefaults.standard.string(forKey: "user_selected_color"),
   let presetColor = PresetColor(rawValue: rawValue) {
    let restoredColor = presetColor.color
}

这种方案没有任何转换损耗,还能完整保留动态颜色的所有系统适配特性。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 06:36:03