从Data对象还原颜色时,如何获取对应系统颜色名称?
解决从归档Data中获取系统颜色名称的问题
原代码仅通过NSKeyedArchiver归档UIColor的颜色数值信息,系统并不会存储systemRed这类颜色名称标识符,因此解码后无法直接获取名称。以下是具体解决思路和实现代码:
核心思路
- 手动维护系统颜色与名称的映射表(系统无公开API直接获取颜色对应的名称)
- 创建自定义归档对象,同时存储
UIColor实例和对应的颜色名称 - 扩展
Color类,修改编码/解码逻辑,处理自定义归档对象 - 提供同时返回颜色和名称的解码方法
实现代码
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
相关产品推荐
相关产品推荐

