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

从Data对象还原颜色时,如何获取对应系统颜色名称?

解决从归档Data中获取系统颜色名称的问题

原代码仅通过NSKeyedArchiver归档UIColor的颜色数值信息,系统并不会存储systemRed这类颜色名称标识符,因此解码后无法直接获取名称。以下是具体解决思路和实现代码:

核心思路

  1. 手动维护系统颜色与名称的映射表(系统无公开API直接获取颜色对应的名称)
  2. 创建自定义归档对象,同时存储UIColor实例和对应的颜色名称
  3. 扩展Color类,修改编码/解码逻辑,处理自定义归档对象
  4. 提供同时返回颜色和名称的解码方法

实现代码

1. 系统颜色-名称映射表

// 系统颜色到名称的映射,可根据需求补充更多系统颜色
private let systemColorNameMap: [UIColor: String] = [
    UIColor.systemRed: "systemRed",
    UIColor.systemGreen: "systemGreen",
    UIColor.systemBlue: "systemBlue",
    UIColor.systemOrange: "systemOrange",
    UIColor.systemYellow: "systemYellow",
    UIColor.systemGray: "systemGray",
    UIColor.systemGray2: "systemGray2",
    UIColor.systemGray3: "systemGray3",
    UIColor.systemGray4: "systemGray4",
    UIColor.systemGray5: "systemGray5",
    UIColor.systemGray6: "systemGray6"
]

2. 自定义归档对象

创建同时存储颜色和名称的可归档类:

class ColorArchiveItem: NSObject, NSCoding {
    let color: UIColor
    let name: String?
    
    init(color: UIColor, name: String?) {
        self.color = color
        self.name = name
        super.init()
    }
    
    func encode(with coder: NSCoder) {
        coder.encode(color, forKey: "color")
        coder.encode(name, forKey: "name")
    }
    
    required init?(coder: NSCoder) {
        guard let color = coder.decodeObject(of: UIColor.self, forKey: "color") else {
            return nil
        }
        self.color = color
        self.name = coder.decodeObject(forKey: "name") as? String
        super.init()
    }
}

3. 修改Color扩展的编码/解码逻辑

extension Color {
    // 解码:同时返回Color实例和对应的名称
    static func colorAndNameFrom(data: Data) -> (color: Color, name: String?) {
        do {
            guard let item = try NSKeyedUnarchiver.unarchivedObject(ofClass: ColorArchiveItem.self, from: data) else {
                return (Color.clear, nil)
            }
            return (Color(item.color), item.name)
        } catch {
            print(error)
            return (Color.clear, nil)
        }
    }
    
    // 编码:打包颜色和对应的系统名称
    func encodeToData() -> Data {
        let uiColor = UIColor(self)
        // 匹配当前颜色对应的系统名称
        let name = systemColorNameMap.first(where: { $0.key.isEqual(uiColor) })?.value
        let item = ColorArchiveItem(color: uiColor, name: name)
        
        do {
            return try NSKeyedArchiver.archivedData(withRootObject: item, requiringSecureCoding: false)
        } catch {
            print(error)
            let fallbackItem = ColorArchiveItem(color: UIColor.clear, name: nil)
            return try! NSKeyedArchiver.archivedData(withRootObject: fallbackItem, requiringSecureCoding: false)
        }
    }
}

4. 使用示例

// 编码系统颜色
let colorData = Color.systemRed.encodeToData()

// 解码并获取颜色名称
let result = Color.colorAndNameFrom(data: colorData)
print("Color: \(result.color), Name: \(result.name ?? "Unknown")")
// 输出:Color: systemRed, Name: systemRed

注意事项

  • 系统颜色是单例对象,使用isEqual可以准确匹配映射表中的条目
  • 若iOS版本更新新增系统颜色,需手动补充到systemColorNameMap中
  • 非系统颜色解码后name会返回nil,可根据需求扩展自定义颜色名称的存储逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 17:15:28